In 运算符§

有关infix but的详细信息,请参阅主要文档 in context

multi infix:<but>(Mu $obj1Mu   $roleis assoc<non>
multi infix:<but>(Mu $obj1Mu:D $obj2is assoc<non>

使用 $role 创建 $obj 的副本。由于 $obj 没有被修改,因此 but 可用于使用 mixin 创建不可变的值。

如果 $role 仅提供一个属性,则可以在括号中传递初始化程序

role Answerable {
    has $.answer;
}
my $ultimate-question = 'Life, the Universe and Everything' but Answerable(42);
say $ultimate-question;         # OUTPUT: «Life, the Universe and Everything␤» 
say $ultimate-question.^name;   # OUTPUT: «Str+{Answerable}␤» 
say $ultimate-question.answer;  # OUTPUT: «42␤» 

您可以提供一个实例化对象,而不是一个 role。在这种情况下,运算符将自动为您创建一个 role。该 role 将包含一个与 $obj.^name 同名的单个方法,并返回 $obj

my $forty-two = 42 but 'forty two';
say $forty-two+33;    # OUTPUT: «75␤» 
say $forty-two.^name# OUTPUT: «Int+{<anon|1>}␤» 
say $forty-two.Str;   # OUTPUT: «forty two␤» 

调用 ^name 表明该变量是带有匿名对象混合的 Int。但是,该对象是 Str 类型,因此该变量通过 mixin 赋予了一个具有该名称的方法,这是我们在最后一句话中使用的方法。

我们还可以混合类,即使是即时创建的类。

my $s = 12 but class Warbles { method hi { 'hello' } }.new;
say $s.Warbles.hi;    # OUTPUT: «hello␤» 
say $s + 42;          # OUTPUT: «54␤» 

要访问混合的类,如上所述,我们使用类名,如第二句话所示。如果已经存在同名方法,则最后混合的 role 优先。可以在括号中提供用逗号分隔的方法列表。在这种情况下,将在运行时报告冲突。