重载类的运算符

问题描述 投票:11回答:2

假设我有以下课程:

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;
}

我将如何以与上一课中的+相同的方式为一个类重载一个运算符(例如,Str)?

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

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

operator-overloading perl6 raku
2个回答
12
投票

在Perl 6中,运算符被认为是当前语言的一部分。与当前语言相关的所有内容都是词法定义的(即my-scoped)。因此,multi sub是正确使用的东西。

如果将此代码放在模块中,您可能还希望使用multi为运算符标记is export

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

因此,useimport模块的用户可以使用它(use实际上是根据import定义的,import将符号导入词法范围)。

虽然有些运算符默认委托给方法(例如,prefix:<+>调用Numeric),但两者之间没有1:1的关系,对于大多数运算符,它们的实现直接在运算符sub中(或分布在许多multi subs上)。

此外,这组运算符是开放的,因此不仅限于重载现有运算符,还可以引入新运算符。当操作符的新含义与所用符号的正常语义没有明确相关时,这是鼓励的;例如,重载+以进行矩阵添加是明智的,但对于某些不可能被视为一种加法的东西,新的运算符将是更好的选择。


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)µ"

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

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

multi infix:<~>(A:U $lhs, A:U $rhs) {
    'µ'
}

希望这能回答你的问题。

© www.soinside.com 2019 - 2024. All rights reserved.