一类的重载运算符

uzl*_*xxx 12 operator-overloading perl6 raku

假设我有以下课程:

class A {
    has $.val;

    method Str { $!val ~ 'µ'  }  
}

# Is this the right way of doing it?
multi infix:<~>(A:D $lhs, A:D $rhs) {
    ('(', $lhs.val, ',', $rhs.val, ')', 'µ').join;
}
Run Code Online (Sandbox Code Playgroud)

如何以与上一类+相同的方式重载某个类的运算符(例如)Str

我猜这仅适用于在实例对象上调用的方法,并且multi operator-type:<OP>(T $lhs, T $rhs) { }对运算符使用语法是正确的解决方法,但我不确定。

例如,在Python中,以运算符(例如operator.__add__)和运算符(例如+)命名的特殊方法之间似乎存在对应关系。此外,自定义类的任何运算符重载都在该类内部完成。

Jon*_*ton 13

在Perl 6中,运算符被视为当前语言的一部分。与当前语言相关的所有事物均以词法定义(即my-scoped)。因此,multisub是正确的用法。

如果将此代码放在模块中,您可能还想用标记multi操作员is export

multi infix:<~>(A:D $lhs, A:D $rhs) is export {
    ('(', $lhs.val, ',', $rhs.val, ')', 'µ').join;
}
Run Code Online (Sandbox Code Playgroud)

这样,模块useimport该模块的用户就可以使用它(use实际上是根据定义的import,并将import符号导入到词法范围内)。

虽然有一些运算符默认情况下委托给方法(例如prefix:<+>call Numeric),但两者之间没有1:1关系,并且对于大多数运算符而言,它们的实现直接在运算符中sub(或散布在许多multi subs中)。

此外,运算符集是开放的,因此,不仅限于重载现有运算符,还可以引入新的运算符。当操作符的新含义与所用符号的常规语义没有明确关联时,鼓励使用此方法。例如,重载+来做矩阵加法是明智的,但是对于某些可能不被视为加法的事物,新的运算符将是一个更好的选择。


Eli*_*sen 7

class A {
    has $.val;

    method Str { $!val ~ 'µ'  }
}

multi infix:<~>(A:D $lhs, A:D $rhs) {
    ('(', $lhs.val, ',', $rhs.val, ')', 'µ').join;
}

dd A.new(val => "A") ~ A.new(val  => "B"); # "(A,B)µ"
Run Code Online (Sandbox Code Playgroud)

是的,那是正确的方法。如果要覆盖+,则要创建的子名称为infix:<+>

您还可以使用:U“类型笑脸” 为类型对象提供大小写,例如:

multi infix:<~>(A:U $lhs, A:U $rhs) {
    'µ'
}
Run Code Online (Sandbox Code Playgroud)

希望这能回答您的问题。