Raku 类中的 $.attribute 和 self.attribute 有什么区别?

uzl*_*xxx 5 methods method-invocation raku

例如,在此类中,Foo两个方法bc返回相同的值:

class Foo {
    method a { 42     }
    method b { $.a    }
    method c { self.a }
}

my $foo = Foo.new;
say $foo.a; #=> 42
say $foo.b; #=> 42
say $foo.c; #=> 42
Run Code Online (Sandbox Code Playgroud)

我注意到我可以对其他 sigil 和 twigil 组合做同样的事情,例如@.scoresvs self.score%.matchesvsself.matches等。

编辑:我将这个问题标记为重复,但是正如 librasteve 指出的那样,我没有意识到另一个问题的答案中提到的微妙区别不是焦点,并且可能很容易被错过,特别是对于 Raku 的新手来说。

uzl*_*xxx 4

正如在另一个 SO 问题的答案中简要提到的,$.method是一种简写$(self.method),表示方法的返回值在项目或标量上下文中逐项列出或处理。或者,您可以item 显式调用self.method,即,self.method.item

\n

a如果方法返回一个列表,则这种上下文化会更加明显:

\n
class Foo {\n    method a { 42, 84 }\n    method b { $.a    }\n    method c { self.a }\n}\n\nmy $foo = Foo.new;\ndd $foo.a; #=> \xc2\xab(42, 84)\xe2\x90\xa4\xc2\xbb\ndd $foo.b; #=> \xc2\xab$(42, 84)\xe2\x90\xa4\xc2\xbb\ndd $foo.c; #=> \xc2\xab(42, 84)\xe2\x90\xa4\xc2\xbb\n
Run Code Online (Sandbox Code Playgroud)\n

方法a并按c原样返回列表,并且方法b已对其进行了逐项列出。因此,$.a返回一个逐项列表,同时self.a返回一个没有任何上下文的列表。

\n

展示这一点的另一种方法是循环每个方法的返回值并查看其行为:

\n
.say for $foo.a; #=> \xc2\xab42\xe2\x90\xa484\xe2\x90\xa4\xc2\xbb\n.say for $foo.b; #=> \xc2\xab(42 84)\xe2\x90\xa4\xc2\xbb\n.say for $foo.c; #=> \xc2\xab42\xe2\x90\xa484\xe2\x90\xa4\xc2\xbb\n
Run Code Online (Sandbox Code Playgroud)\n

如此处所示,b\ 的返回值被视为单个项目,这与for迭代列表中每个元素的其他方法不同。@.method和也发生上下文化%.method,如下所示:

\n
class Bar {\n    method a { 1..4 }\n    method b { @.a }\n    method c { %.a }\n    method d { self.a }\n}\n\nmy $bar = Bar.new;\ndd $bar.a; #=> \xc2\xab1..4\xe2\x90\xa4\xc2\xbb\ndd $bar.b; #=> \xc2\xab(1, 2, 3, 4)\xe2\x90\xa4\xc2\xbb\ndd $bar.c; #=> \xc2\xab{"1" => 2, "3" => 4}\xe2\x90\xa4\xc2\xbb\ndd $bar.d; #=> \xc2\xab1..4\xe2\x90\xa4\xc2\xbb\n
Run Code Online (Sandbox Code Playgroud)\n

下表总结了上下文化方法调用的行为:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n
上下文方法调用简写为明确的情境化
$.method$(self.method)self.method.item
@.method@(self.method)self.method.list
%.method%(self.method)self.method.hash
\n