【问题标题】:Using ampersands and parens when calling a Perl sub调用 Perl 子程序时使用 & 和括号
【发布时间】:2016-03-09 21:39:45
【问题描述】:
#!/usr/bin/perl

sub t {
  print "in t\n";
  print "@_\n";
  &s;
}

sub s {
  print "in s\n";
  print "@_\n";
}

t(1,2);
print "out\n";
print "@_\n";

输出:

in t
1 2
in s
1 2
out

如你所见,&s 在没有传递参数时输出1 2。这是功能还是错误?

测试版本为 5.8.8。

【问题讨论】:

  • 真正的问题是,Perl 是一个特性还是一个错误?

标签: perl


【解决方案1】:

使用&NAME; 语法调用子例程会使当前@_ 对其可见。这记录在perlsub:

如果使用& 形式调用子程序,则参数列表是可选的,如果省略,则不会为子程序设置@_ 数组:调用时的@_ 数组是可见的改为子程序。这是新用户可能希望避免的一种效率机制。

所以,这绝对是一个功能。

【讨论】:

  • 还值得注意的是,@_ 与调用子例程中的数组相同,因此如果被调用的子例程将@_ 更改为shift 或类似的东西,那么更改将是可见的在通话后@_。 (这就是效率的来源)
  • 另外值得注意的是,使用goto &mysub 可以进行jump 而不是call,这意味着当前堆栈帧被丢弃,因此不会浪费内存。这样你就可以递归地、尾递归地编码循环,更准确地说。见goto &NAME
【解决方案2】:

当在子名称之前使用& 并且没有传递参数列表时,当前的@_ 作为参数传递。所以,这是一个特点。

以下是调用子程序的不同方式:

NAME(LIST); # & is optional with parentheses.
NAME LIST;  # Parentheses optional if predeclared/imported.
&NAME(LIST); # Circumvent prototypes.
&NAME;      # Makes current @_ visible to called subroutine.

来自perldoc perlsub

【讨论】:

  • 这里的Circumvent prototypes 是什么意思?
  • sub foo ($$) { },括号声明原型。最容易记住的是:使用 name(LIST),除非你有理由不这样做。
  • 我列出了调用 sub 的所有可能方式,这是从 perlsub 中引用的。查一下。
  • 我想你自己弄糊涂了。我列出的 4 件事是为了让您大致了解如何调用 sub 以及它们的含义。
【解决方案3】:

直接从骆驼嘴里说出来:

如果使用“&”形式调用子程序,则参数列表是可选的,如果省略,则不会为子程序设置@_数组:调用时的@_数组是可见的改为子程序。这是新用户可能希望避免的一种效率机制。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-23
    • 2013-04-15
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 2019-06-29
    • 1970-01-01
    相关资源
    最近更新 更多