函数声明“sub function($$)”的作用是什么?意思是?

发布于 2024-08-25 17:42:50 字数 118 浏览 6 评论 0原文

我已经使用 Perl 一段时间了,但今天我遇到了这段代码:

sub function1($$)
{
   //snip
}

这在 Perl 中意味着什么?

I have been using Perl for some time, but today I came across this code:

sub function1($)
{
   //snip
}

What does this mean in Perl?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧伤慢歌 2024-09-01 17:42:50

它是一个具有带有两个标量参数的 原型 的函数。


对于一般情况下不实际使用 Perl 原型有强有力的论据 - 正如下面的评论所述。最有力的论据可能是:

2008 年 StackOverflow 上有一个讨论:

MooseX::Method::Signatures 模块中可能的替代品。

It is a function with a prototype that takes two scalar arguments.


There are strong arguments for not actually using Perl prototypes in general - as noted in the comments below. The strongest argument is probably:

There's a discussion on StackOverflow from 2008:

There's a possible replacement in the MooseX::Method::Signatures module.

‘画卷フ 2024-09-01 17:42:50

正如另一个答案提到的, $$ 声明了一个原型。另一个答案没有说明原型的用途。它们不是用于输入验证,而是用于解析器的提示。

想象一下,您有两个函数声明如下:

sub foo($)  { ... }
sub bar($) { ... }

现在,当您编写一些不明确的内容时,例如:

foo bar 1, 2

Perl 知道将括号放在哪里; bar 需要两个参数,因此它会消耗最接近的两个参数。 foo 接受一个参数,因此它接受 bar 的结果和两个参数:

foo(bar(1,2))

另一个例子:

bar foo 2, 3

同理; foo 需要一个参数,所以它得到 2。 bar 需要两个参数,所以它得到 foo(2) 和 3:

bar(foo(2),3)

这是 Perl 的一个非常重要的部分,所以将其视为“从不使用”对你不利。几乎每个内部函数都使用原型,因此通过了解它们在您自己的代码中如何工作,您可以更好地了解内置函数如何使用它们。这样您就可以避免不必要的括号,从而使代码看起来更美观。

最后,我将警告您注意一种反模式:

package Class;
sub new ($) { bless $_[1] }
sub method ($) { $_[0]->{whatever} }

当您将代码作为方法调用时(Class->method$instance->method),原型检查完全没有意义。如果你的代码只能作为方法调用,那么添加原型是错误的。我见过一些流行的模块可以做到这一点(你好,XML::Compile),但这是错误的,所以不要这样做。如果您想记录要传递多少个参数,可以这样:

sub foo {
    my ($self, $a, $b) = @_; # $a and $b are the bars to fooify
    ....

use MooseX::Method::Signatures;

method foo(Bar $a, Bar $b) { # fooify the bars
    ....

foo($$) 不同,这些是有意义且可读的。

As the other answer mentions, the $$ declares a prototype. What the other answer doesn't say is what prototypes are for. They are not for input validation, they are hints for the parser.

Imagine you have two functions declared like:

sub foo($)  { ... }
sub bar($) { ... }

Now when you write something ambiguous, like:

foo bar 1, 2

Perl knows where to put the parens; bar takes two args, so it consumes the two closest to it. foo takes one arg, so it takes the result of bar and the two args:

foo(bar(1,2))

Another example:

bar foo 2, 3

The same applies; foo takes one arg, so it gets the 2. bar takes two args, so it gets foo(2) and 3:

bar(foo(2),3)

This is a pretty important part of Perl, so dismissing it as "never use" is doing you a disservice. Nearly every internal function uses prototypes, so by understanding how they work in your own code, you can get a better understanding of how they're used by the builtins. Then you can avoid unnecessary parentheses, which makes for more pleasant-looking code.

Finally, one anti-pattern I will warn you against:

package Class;
sub new ($) { bless $_[1] }
sub method ($) { $_[0]->{whatever} }

When you are calling code as methods (Class->method or $instance->method), the prototype check is completely meaningless. If your code can only be called as a method, adding a prototype is wrong. I have seen some popular modules that do this (hello, XML::Compile), but it's wrong, so don't do it. If you want to document how many args to pass, how about:

sub foo {
    my ($self, $a, $b) = @_; # $a and $b are the bars to fooify
    ....

or

use MooseX::Method::Signatures;

method foo(Bar $a, Bar $b) { # fooify the bars
    ....

Unlike foo($$), these are meaningful and readable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文