方法可以视为常规子例程吗?

时间:2019-07-15 13:47:19

标签: perl6 subroutine raku

是否可以将方法分配给变量并将它们作为类中的参数传递给子例程?

我知道可以通过其他方法中的self.self!(或任何称为显式调用者)访问它们,但是我想知道是否可以将方法的代码对象作为参数传递转到另一种方法。

2 个答案:

答案 0 :(得分:10)

您是否考虑过传递方法名称?

class Foo {
    method bar($a) { dd $a }
}
my $name = "bar";
Foo."$name"(42);  # 42

该语法要求需要字符串化括号,以表明您要调用该方法。如果您确实想使用Method对象并将其传递给您,可以,但是没有真正好的语法:

class Foo {
    method bar($a) { dd $a }
}
constant &B = Foo.^find_method("bar");
B(Foo, 42)  # 42

在此示例中,常量&B在编译时创建。但是您也可以在运行时调用此方法,例如当方法名称在变量中时:

my $name = "bar";
my $method = Foo.^find_method($name);
$method(Foo, 42);

但是,在那种情况下,使用."$name"()语法可能会更好。有关更多信息,请参见https://docs.perl6.org/routine/find_method

答案 1 :(得分:9)

有两种通用的机制可以将方法定为first class citizen(可以作为参数传递的东西),具体取决于方法是否受has限制(几乎全部) )或my范围。

.^find_method...找到一个has作用域方法

绝大多数方法都保存在类中,并且在没有显式范围声明符的情况下进行声明。所有这些(隐式地)has的范围都限于包含它们的类。

要传递has范围内的方法作为参数,您需要查找。 find 操作必须相对于某个包含该方法或从包含该方法的类继承的类进行初始化。即使您知道该方法在要从中发起 find 操作的类中也是如此。共有三个选项:

    ugexe ++指出,
  • .^find_method是常用的工具。如您所料,它将从.^find_method倡导者的类开始,在Method Resolution Order中搜索继承的类。

  • 在极少数情况下,您可能想使用.^find_method_qualified。这比搜索者的班级从MRO更高的位置开始搜索。

  • 为完整性起见,我将包括另一种方法:.^lookup。但是请阅读文档中的警告。您几乎可以肯定不应该使用此方法,特别是如果您想做的是 call 方法。请改用.^find_method...方法之一。

所以:

.has-way given class {
  method has-way { my $m = self.^find_method: 'm'; self.m-as-arg: $m }
  method m-as-arg ($m) { say self.$m } # has way
  method m { 'has way' }
}

&foo引用范围为my的方法

一些方法不受has限制,而是用my声明。

对于这些 lexical 方法,将它们作为参数传递的机制是简单地以前缀&来引用它们,就像处理sub一样

所以:

.my-way given class {
  method my-way { self.m-as-arg: &m }
  method m-as-arg ($m) { say self.$m }     # my way
  my method m { 'my way' }
}