通读https://docs.perl6.org/language/packages#Package-qualified_names时,将使用以下语法概述合格的包装变量:
Foo::Bar::<$quux>; #..as an alternative to Foo::Bar::quux;
作为参考,本文中用作示例的软件包结构为:
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;
}
}
同一页面上指出,这种资格认证不适用于访问上面列出的Foo :: Bar程序包中的&zape
:
(不适用于&zape变量)
但是,如果我尝试:
Foo::Bar::<&zape>; # instead of &Foo::Bar::zape;
解决就可以了。
我误解了文档还是完全错过了要点?例如,使用代码引用变量而不是标量,它“不起作用”的背后的逻辑是什么?
答案 0 :(得分:5)
我不知道它们之间的区别,但是Foo::Bar::<&zape>
也可以修改为使用{}
代替<>
,然后可以将其与文字以外的其他东西一起使用,例如:
my $name = '&zape';
Foo::Bar::{$name}()
或
my $name = 'zape';
&Foo::Bar::{$name}()
答案 1 :(得分:4)
Package :: <&var>和&Package :: var之间没有区别。
package Foo { our $var = "Bar" };
say $Foo::var === Foo::<$var>; # OUTPUT: «True»
同上(当然):
package Foo { our &zape = { "Bar" } };
say &Foo::zape === Foo::<&zape>;# OUTPUT: «True»
文档(有些令人困惑)试图说的是,只有在使用我们的声明时,才能访问包范围变量。 zape
有两个,其中一个具有词法作用域(默认情况下,子类具有词法作用域),因此您无法访问该词法作用域。我在文档存储库中提出了this issue,并将尝试尽快对其进行修复。
答案 2 :(得分:3)
JJ和Moritz提供了有用的答案。
此nanswer是整个蜡球。在过去几天中,我已经为您的问题写了一些nanswer,并将其废弃。没有一个非常有用。我不确定这是不是,但是我已经确定我终于有了一个值得发布的东西的第一个版本,不管它当前是否有用。
在第一部分中,我的答案是一系列观察和问题。我还希望根据我从拼写编译器代码以理解我们所看到的内容中学到的内容,对我的观察内容进行一个解释。 (目前,我只是将该过程的开始记为该答案的后半部分。)
Package::<&var>
与&Package::var
之间的差异(如果有)?
它们是根本不同的语法。它们在您可以编写它们的地方不能完全互换。它们导致不同的评估。他们的结果可能是不同的。
让我们迈出一大步,找出差异。
say Package::<&var>; # compile-time error: Undeclared name: Package
因此,暂时忘记::<...>
位。 P6正在查看该Package
位,并要求它是一个已经声明的名称。这似乎很简单。
say &Package::var; # (Any)
有所不同!由于某种原因,对于第二种语法,P6不会出现这两个任意名称(Package
和var
)的问题。谁知道&
在做什么。为什么是(Any)
而不是(Callable)
或Nil
?
让我们尝试声明这些内容。首先:
my Package::<&var> = { 42 } # compile-time error: Type 'Package' is not declared
好。但是,如果我们声明Package
并没有真正改善:
package Package {}
my Package::<&var> = { 42 } # compile-time error: Malformed my
好的,重新开始,不带package
声明。那其他语法呢?
my &Package::var = { 42 }
是的。 P6接受此代码。现在,在接下来的几行中,我们假设上面的声明。怎么样:
say &Package::var(); # 42
\ o /那么我们可以使用其他语法吗?:
say Package::<&var>(); # compile-time error: Undeclared name: Package
不。似乎my
没有声明其中带有Package
的{{1}}。也许它声明为&var
,其中&Package::var
恰好是名称的一部分,但与软件包无关吗? P6支持一堆"pseudo" packages。其中之一是::
:
LEXICAL
宾果。是吗?
say LEXICAL::; # PseudoStash.new(... &Package::var => (Callable) ...
我们的say LEXICAL::<&Package::var>(); # Cannot invoke this object
# (REPR: Uninstantiable; Callable)
发生了什么事?
嗯。让我们从全新的开始,以完全不同的方式创建{ 42 }
:
&Package::var
哇。现在,假设上面的行并尝试添加更多行:
package Package { our sub var { 99 } }
say &Package::var(); # 99
say Package::<&var>(); # 99
鉴于我们之前的尝试,这是可以预期的。怎么样:
my Package::<&var> = { 42 } # Compile-time error: Malformed my
现在一切都有意义了吗? ;)
1 在查看the Rakudo compiler的源代码之前,我花了很长时间试图弄清实际交易是什么。这是一个脚注,涵盖了我最初的编译器拼写。我希望明天继续,并在本周末将这个答案变成答案。
好消息是这只是P6代码-Rakudo的大部分代码都是用P6编写的。
坏消息是知道在哪里看。您可能会看到my &Package::var = { 42 } # Cannot modify an immutable Sub (&var)
目录,然后是the compiler overview。但是,您会发现概述文档自2010年以来几乎没有被使用过!不要打扰也许Andrew Shitov's "internals" posts可以帮助您确定方向?继续...
在这种情况下,我感兴趣的是了解doc
和Package::<&var>
语法形式的确切性质。当我在GH的回购搜索字段中键入“ syntax”时,列出的第二个文件是the Perl 6 Grammar。宾果游戏。
现在有丑闻了。 Perl 6语法文件是6K LOC,看起来非常吓人。但是我觉得保持冷静很有意义。
接下来,我想知道要在页面上搜索什么。 &Package::var
获得600场比赛。嗯::
仅为1,但是它在错误消息中。但是在什么呢?在token morename
中。看着那我可能发现不相关。但是令牌开头附近的::<
只是票证。在页面上搜索'::'
可获得10个匹配项。前4个(从文件开头)是更多错误消息。接下来的两个在上面的'::'
令牌中。还剩4场比赛。
下一个出现在token term:sym<name>
的四分之一处。一个名字”。 .o((morename
也许相关吗?)
接下来,token typename
。一个“类型名”。 .o(Undeclared name: Package
也许这也很重要吗?)
token methodop
。绝对不相关。