该int类有一个方法is_prime
,所以我想,只是笑声,我想一些其他方法增加Int
了一些做数论的东西我的爱好项目.
我以为我可以这样做:
class Int { method is-even (Int:D $number ) returns Bool:D { return False if $number % 2; return True; } } say 137.is-even;
但这不起作用:
===SORRY!=== P6opaque: must compose before allocating
我不知道这是否意味着我不能这样做或者我做错了.
我可以很容易地创建一个继承自的新类Int
,但这不是我感兴趣的:
class MyInt is Int { method is-even () returns Bool:D { return False if self % 2; return True; } } my $n = MyInt.new(138); say $n.is-even;
我不是在寻找变通方法或替代解决方案.
这有语法糖 - augment
:
use MONKEY-TYPING; augment class Int { method is-even() returns Bool:D { return False if self % 2; return True; } }
增加一个课程被认为是危险的有两个原因:第一,远距离行动,第二,因为(据我所知),有潜力 未定义的行为 deoptimization,因为它可能会使各种方法缓存处于无效状态.
因此,MONKEY-TYPING
在允许使用之前提供pragma 的要求.
另外,请注意is-even
可以写得更紧凑self %% 2
.
呵呵,这有效,我以为我以前尝试过,而且比我在问题中提出的要好。
Int.^add_method( 'is-even', method () returns Bool:D { return False if self % 2; return True; } ); say 137.is-even;
不过,我不确定这是否行得通。该add_method文档说的类型由之前,我们只能这样做。如果我打电话Int.^methods
的is-even
显示不出来。尽管如此,它似乎是可以调用的并且做对了。
玩多了,我想我可以创建一个不附加到任何类的方法,然后在一个对象上调用它:
my &is-even = method (Int:D :) returns Bool:D { self %% 2 };
这构造了一个Callable
(请参阅&is-even.WHAT
)。在签名中,我将其约束为一个确定的Int值(Int:D
),但未为其命名。我在类型约束之后添加冒号,以注意第一个参数是倡导者。现在,我可以将该方法应用于我喜欢的任何对象:
say 137.&is-even; say 138.&is-even; say "foo".&is-even; # works, although inside is-even blow up
因为它是词法,所以在不同的维度上很好,但是在错误类型的对象可能会调用它的情况下不好。在认为它具有可以分派到的方法后,该错误就会出现。