包限定名称。Package :: <&var>与&Package :: var之间的差异(如果有)?

drc*_*law 7 package perl6

通过阅读https://docs.perl6.org/language/packages#Package-qualified_names,它概述了使用以下语法的合格软件包变量:

Foo::Bar::<$quux>; #..as an alternative to Foo::Bar::quux;
Run Code Online (Sandbox Code Playgroud)

作为参考,在本文档中用作示例的软件包结构为:

class Foo {
    sub zape () { say "zipi" }
    class Bar {
        method baz () { return 'Þor is mighty' }
        our &zape = { "zipi" };   #this is the variable I want to resolve
        our $quux = 42;
    }
}
Run Code Online (Sandbox Code Playgroud)

同一页面上指出,&zape在上面列出的Foo :: Bar包中无法使用这种资格认证方式:

(这不适用于&zape变量)

但是,如果我尝试:

Foo::Bar::<&zape>;  # instead of   &Foo::Bar::zape;
Run Code Online (Sandbox Code Playgroud)

它解决就好了。

我误解了文档还是完全错过了重点?例如,代码引用变量与标量“不起作用”背后的逻辑是什么?

mor*_*itz 5

我不知道有什么区别,但是Foo::Bar::<&zape>也可以将其修改为使用{}代替<>,然后可以将其与文字以外的其他东西一起使用,例如:

my $name = '&zape';
Foo::Bar::{$name}()
Run Code Online (Sandbox Code Playgroud)

要么

my $name = 'zape';
&Foo::Bar::{$name}()
Run Code Online (Sandbox Code Playgroud)


rai*_*iph 4

JJ 和莫里茨提供了有用的答案。

这个答案完全是另一个蜡球。在过去的几天里,我已经写下了并丢弃了您问题的几个答案。没有一个非常有用。我也不确定这是不是,但我决定我终于得到了值得发布的东西的第一个版本,无论它当前的有用性如何。

在第一部分中,我的答案只是一系列观察和问题。我还希望根据我从探索编译器代码中收集到的信息来添加对我的观察结果的解释,以理解我们所看到的内容。(现在我刚刚把这个过程的开始写成这个答案的后半部分。)

Package::<&var>与 之间的差异(如果有)&Package::var

它们的语法根本不同。它们在您可以编写的位置上不能完全互换。它们会导致不同的评价。他们的结果可能是不同的。

让我们逐步了解许多变化,找出差异。

say Package::<&var>; # compile-time error: Undeclared name: Package
Run Code Online (Sandbox Code Playgroud)

所以,::<...>暂时忘记这一点。P6 正在关注这Package一点并要求它是一个已经声明的名称。这看起来很简单。

say &Package::var; # (Any)
Run Code Online (Sandbox Code Playgroud)

差别很大!由于某种原因,对于第二种语法,P6 没有声明这两个任意名称(Package和)没有问题。var谁知道它在做什么&。为什么是它(Any)而不是(Callable)Nil

让我们尝试声明这些事情。第一的:

my Package::<&var> = { 42 } # compile-time error: Type 'Package' is not declared
Run Code Online (Sandbox Code Playgroud)

好的。但如果我们宣称Package事情并没有真正改善:

package Package {}
my Package::<&var> = { 42 } # compile-time error: Malformed my
Run Code Online (Sandbox Code Playgroud)

好的,再次从头开始,无需package声明。其他语法怎么样?:

my &Package::var = { 42 }
Run Code Online (Sandbox Code Playgroud)

耶。P6 接受此代码。现在,对于接下来的几行,我们将假设上面的声明。关于什么:

say &Package::var(); # 42
Run Code Online (Sandbox Code Playgroud)

\o/ 那么我们可以使用其他语法吗?:

say Package::<&var>(); # compile-time error: Undeclared name: Package
Run Code Online (Sandbox Code Playgroud)

没有。似乎my没有声明 a其中有Packagea 。&var也许它声明了 a &Package::var,其中::恰好是名称的一部分但与包无关?P6支持一堆“伪”包。其中之一是LEXICAL

say LEXICAL::; # PseudoStash.new(... &Package::var => (Callable) ... 
Run Code Online (Sandbox Code Playgroud)

答对了。或者是吗?

say LEXICAL::<&Package::var>(); # Cannot invoke this object
                                # (REPR: Uninstantiable; Callable)
Run Code Online (Sandbox Code Playgroud)

我们的怎么了{ 42 }

唔。让我们从头开始,&Package::var以完全不同的方式进行创建:

package Package { our sub var { 99 } }
say &Package::var();   # 99
say Package::<&var>(); # 99
Run Code Online (Sandbox Code Playgroud)

哇。现在,假设上面的这些行并尝试添加更多:

my Package::<&var> = { 42 } # Compile-time error: Malformed my
Run Code Online (Sandbox Code Playgroud)

鉴于我们之前的上述尝试,这是可以预料到的。关于什么:

my &Package::var = { 42 }   # Cannot modify an immutable Sub (&var)
Run Code Online (Sandbox Code Playgroud)

现在一切都有意义了吗?;)

深入研究编译器代码,检查语法

1在查看Rakudo 编译器的源代码之前,我花了很长时间试图弄清楚到底什么。这是一个脚注,涵盖了我最初的编译器探索。我希望明天继续,并在本周末将这个nanswer变成答案。

好消息是它只是 P6 代码——Rakudo 的大部分都是用 P6 编写的。

坏消息是知道去哪里寻找。您可能会看到doc目录,然后看到编译器概述。但随后您会发现,自 2010 年以来,概述文档几乎没有被修改过!别打扰。也许安德鲁·什托夫(Andrew Shitov)的“内部”帖子会帮助您定位?继续...

在这种情况下,我感兴趣的是理解语法的精确性质Package::<&var>&Package::var形式。当我在 GH 的存储库搜索字段中输入“syntax”时,列出的第二个文件是Perl 6 Grammar。答对了。

现在传来了丑闻。Perl 6 Grammar 文件有 6K LOC,看起来超级吓人。但当我保持冷静时,我发现这一切都是有道理的。

接下来,我想知道要在页面上搜索什么。::打进 600 多场比赛。唔。::<只是 1,但它出现在错误消息中。但在什么方面呢?在token morename。看看这个,我发现它可能相关。但'::'令牌的开头附近只是票据。搜索该页面会'::'产生 10 个匹配项。前 4 条(从文件开头算起)是更多错误消息。接下来的两个在上面的morename标记中。还剩 4 场比赛。

下一个出现在四分之一处token term:sym<name>。一个名字”。.oO(Undeclared name: Package所以也许这是相关的?)

下一个,token typename。一个“类型名称”。.oO(Type 'Package' is not declared所以也许这也相关?)

token methodop。绝对不相关。

最后token infix:sym<?? !!>。没有。