perl6子真的是按词法界定的还是有附加词的?

时间:2019-06-26 17:43:35

标签: scope perl6

如果我有如下所示的方块:

{
   say $myVar;
   my $myVar=1;
}

我得到预期的错误:

Variable '$myVar' is not declared 

但是与sub

类似
{
    test();
    my sub test() {
        say "Hello";
    }
}

这将正常运行并显示:

Hello

$myVartest在封闭的块之外都不可见,因此从某种意义上来说,它们都在词法范围内。

由于sub在代码中的位置已定义且可用,因此test的声明必须“提升”到块的顶部。我找不到参考资料来支持这一点。

提示此问题的原因是查看perl中的词法作用域my subs,这在上述第二种情况的perl版本中给出了“未定义的子例程”错误。根据我对词汇范围的理解,这就是我所期望的。

我不加思索地使用它……编写一些测试代码,然后将其包装到文件底部声明的sub中,并从文件的较早位置调用该子项。一切正常!

这确实引发了一个问题:从这个意义上说,perl6 subs真的在词法范围内吗?

2 个答案:

答案 0 :(得分:7)

当Perl6遇到函数调用时,它会对此进行记录,但不会检查该函数是否存在。

因此,以下内容可以编译,但实际上不起作用。 (该函数在调用它的位置不可用。)

burger.addEventListener('click', toggleMenu);
closeArea.addEventListener('click', toggleMenu);

下面,编译器执行相同的操作,但是优化器意识到它甚至无法在任何地方找到对该函数的引用。 (因此,优化器会导致其在编译期间失败。)

foo 1;
my &foo = &say;

与其他变量产生这种差异的原因是,很多时候您可能有一个函数依赖于另一个函数,或者您想将这些函数放在其余的代码之后。
同样,函数的代码通常在编译时就知道了,而变量的值直到赋值后才知道。 (分配在运行时发生。)

人们使用变量和函数的方式基本上是不同的,因此它们的工作方式略有不同。

不需要在使用它们之前声明它们,从而取消了限制。


在Perl5中,函数会根据原型对解析器进行修改,因此,编译器需要先查看声明,然后才能使用该声明来了解应如何解析它们。

bar 1;

在Perl6中,所有函数都像列出一个列表一样进行编译,因此不需要要求将它们预先声明。

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 }

答案 1 :(得分:5)

来自Subroutine Apocalypse

  

Perl 6还允许您将对子例程的声明推迟到文件的后面,但前提是延迟的声明声明要解析的子例程与解析列表运算符的方式一致。基本上,任何无法识别的“裸词”都被假定为临时列表运算符,必​​须在当前编译单元的末尾声明。