当我创建一个以 ^
开头的类方法时,我尝试调用它,它给了我一个错误。
class C {
method ^test () {
"Hi"
}
}
dd C.new.test;
Too many positionals passed; expected 1 argument but got 2
in method test at .code.tio line 1
in block <unit> at .code.tio line 1
如果我在没有前导的情况下使用相同的方法
^
,它工作正常。class C {
method test () {
"Hi"
}
}
dd C.new.test;
"Hi"
我见过模块公开类的方法以
^
开头,这就引出了我的问题。当我定义以 ^
开头的方法名称时,为什么会出现此错误? ?
最佳答案
TL;博士 该方法正在被正确调用。 ^
在 foo.^bar
表示“元方法”。这既不是实例方法也不是类方法。元方法被传递给一个调用者,就像所有方法一样,另一个“原始调用者”对象作为第一个参数。
大多数用户永远不需要考虑这些东西。但是你已经问过了,所以让我们深入研究......
元方法
引用 Meta-object protocol (MOP) Raku 文档页面:
Raku is built on a meta object layer.
此 MOP 层定义了您可以使用的各种内置“元方法”。
例如:
say .^attributes given class bar { has Int $!foo }
这会显示 (Int $!foo)
. .^attributes
方法调用是一种元方法。它被调用(通常是不可见的)元对象,它决定了 Raku 类型在幕后如何工作。在这种情况下,它返回类的属性(has
变量)。但是也可以有用户定义的元方法。声明这些的一种方法是在一个普通的类中:
class {
has Int $!foo;
method ^attributes ($arg) { self, $arg }
}
say baz.^attributes
以上baz
类包括一个 ^attributes
覆盖内置元方法的元方法声明。特别值得注意的是,我添加了一个参数。所有元方法都至少有一个参数(除了一个常规的调用者)。使用此声明,而不是
(Int $!foo)
回应 .^attributes
调用你取 list self, $arg
来自 .^attributes
baz
中的方法类(class)。注意如何
self
既不是 baz
实例对象也不是 baz
类型对象——而是 Perl6::Metamodel::ClassHOW+{<anon>}.new
-- 而 $arg
是 baz
(类型)对象。这个答案的其余部分更详细地解释了正在发生的事情。
一个普通方法调用的回顾
首先,让我们回顾一下典型的方法调用。
语法
foo.bar
导致“bar”方法(消息)被分派(dispatch)到 foo
.如
foo
是一个类的实例,“bar”被分派(dispatch)到该实例。这种方法调用有时称为“实例方法”。如
foo
是 type object对应于一个类,“bar”被分派(dispatch)到该类型对象。这种方法调用有时称为“类方法”。在这两种情况下,“bar”都被分派(dispatch)到
foo
.#
foo.^bar
语法 foo.^bar
是不同的。阅读
^
指向另一个隐藏在上方的物体 foo
,或者实际上任何与类型相关的东西 foo
是。此类对象是
HOW
决定对象如何工作的对象。这些 HOW
对象通常保持不可见状态,使事物运行良好,用户很高兴地不知道它们的存在和他们正在做的工作。 1形式为
foo.^bar
的方法调用通常会导致 Raku 向 foo
发送元方法调用的 HOW
目的。这些元方法需要两个类似 invocant 的参数。这是
HOW
目的。这是作为常规调用者传递的。然后是 foo
目的。这作为第一个普通参数传递给元方法。这就是您拨打
foo.^bar
时通常会发生的情况-- 元方法调用被分派(dispatch)到 foo
的 HOW
对象和 foo
作为存储可以说是“原始调用者”的普通参数传递。#
foo.^bar
当没有内置时 .^bar
元方法如果您拨打
foo.^bar
如果没有这样的方法,你会得到一个错误:42.^bar
产量:No such method 'bar' for invocant of type 'Perl6::Metamodel::ClassHOW'
注意调用者类型是元模型类,而不是 42
或 Int
.如果用户定义的类声明了
^.bar
,然后 Raku 调用它,传递实例/类的 HOW
对象作为调用者,“原始调用者”( foo
)作为第一个普通参数:class foo {
method ^bar ($arg) { self, $arg }
}
say foo.^bar; # (Perl6::Metamodel::ClassHOW+{<anon>}.new (foo))
脚注1 调用
.HOW
在对象上返回其 HOW
:say .HOW given class {} # Perl6::Metamodel::ClassHOW
HOW
对象是 MOP 的一部分,在乐乐深处的一层。大多数开发人员永远不需要明确地挖掘到这个级别。
如果你挖得更深,你就会离开指定的乐。在乐堂
.HOW
的 HOW
对象通常是 NQP目的:say ((.HOW.new given class {}).HOW).^name; # NQPClassHOW
关于raku - 带有 ^ 的类方法名称没有被正确调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54143036/