raku - 带有 ^ 的类方法名称没有被正确调用

标签 raku

当我创建一个以 ^ 开头的类方法时,我尝试调用它,它给了我一个错误。

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 -- 而 $argbaz (类型)对象。
这个答案的其余部分更详细地解释了正在发生的事情。
一个普通方法调用的回顾
首先,让我们回顾一下典型的方法调用。
语法 foo.bar导致“bar”方法(消息)被分派(dispatch)到 foo .
foo是一个类的实例,“bar”被分派(dispatch)到该实例。这种方法调用有时称为“实例方法”。
footype 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)到 fooHOW对象和 foo作为存储可以说是“原始调用者”的普通参数传递。
# foo.^bar当没有内置时 .^bar元方法
如果您拨打 foo.^bar如果没有这样的方法,你会得到一个错误:
42.^bar
产量:
No such method 'bar' for invocant of type 'Perl6::Metamodel::ClassHOW'
注意调用者类型是元模型类,而不是 42Int .
如果用户定义的类声明了 ^.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 的一部分,在乐乐深处的一层。
大多数开发人员永远不需要明确地挖掘到这个级别。
如果你挖得更深,你就会离开指定的乐。在乐堂 .HOWHOW对象通常是 NQP目的:
say ((.HOW.new given class {}).HOW).^name; # NQPClassHOW

关于raku - 带有 ^ 的类方法名称没有被正确调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54143036/

相关文章:

raku - 如何删除列表中的重复项 (Raku)

32-bit - Rakudo x86 32 位预编译安装程序/二进制文件在哪里?

raku - 为什么单个数字无法匹配数组中的 Range 对象?

math - 在 Raku 中表达双重求和序列

raku - Perl6 IO::Socket::Async 截断数据

raku - 为什么在 Perl 6 REPL 中 if False 产生一个空列表之后的命令?

unicode - 如何使 Perl 6 对 Unicode 数据进行往返安全?

module - 如何找到 Perl 6 模块的版本和权限?

raku - 如何在 Perl 6 中创建两个 SetHashes 的并集?

inheritance - 如何通过扩展正在使用的类来扩展模块?