如果我有一个如下所示的块:
{
say $myVar;
my $myVar=1;
}
我得到了预期的错误:
Variable '$myVar' is not declared
但是以类似的方式使用sub
{
test();
my sub test() {
say "Hello";
}
}
此命令运行时不会出现错误,并打印:
Hello
在封闭的块之外,$myVar
和test
都不可见,因此从这个意义上说,它们都是词法作用域。
由于test
在代码中的位置之前已定义并可用,因此sub
必须将其声明“提升”到块的顶部。然而,我找不到一个参考资料来支持这一点。
提出这个问题的原因是查看了perl中的词法作用域my subs
,它在上面第二种情况的perl版本中给出了一个“未定义的子例程”错误。在我对词法作用域的理解中,这是我所期望的。
我不假思索地使用它。编写一些测试代码,稍后将其包装到我的文件底部声明的sub
中,并调用文件中前面的sub。一切正常!
这确实引出了一个问题: perl6 subs真的在这种意义上限定了词法范围吗?
发布于 2019-06-27 03:17:41
当Perl6遇到函数调用时,它会记录下来,但不会检查函数是否在那里。
所以下面的代码将会被编译,但实际上不会工作。(该函数在被调用的地方不可用。)
foo 1;
my &foo = &say;
在下面的代码中,编译器做了同样的事情,但是优化器意识到它甚至找不到任何地方对该函数的引用。(因此优化器会导致它在编译过程中失败。)
bar 1;
与其他变量不同的原因是,很多时候,您可能有一个函数依赖于另一个函数,或者您希望将这些函数放在其余代码之后。
此外,函数的代码通常在编译时是已知的,而变量的值直到赋值之后才知道。(赋值发生在运行时。)
基本上,人们使用变量和函数的方式是不同的,所以它们的工作方式也略有不同。
没有必要在使用它们之前要求它们被声明,所以这个限制被删除了。
在Perl5中,函数根据其原型修改解析器,因此编译器需要在使用它们之前查看声明,以便知道应该如何解析它们。
use v5.10;
sub foo ();
sub bar;
say foo + 1; # foo() + 1 # foo is compiled as a term/constant
say bar + 1; # bar( +1 )
sub foo () { 2 }
sub bar { $_[0] + 2 }
在Perl6中,所有函数都像接受列表一样进行编译,因此不需要预先声明它们。
use v6;
# these two lines don't really change anything.
sub foo () {...}
sub bar ($) {...}
say foo + 1; # foo( +1 ) # optimization failure (too many arguments)
say bar + 1; # bar( +1 )
sub foo () { 2 }
sub bar ( $a ) { $a + 2 }
https://stackoverflow.com/questions/56778434
复制相似问题