14

我正在玩这个小东西,其中一组可以通过翻转测试来充当它的补充。为了完成这项工作,我创建了成员操作符的特殊版本。

class Complement {
    has $.set;
    }

multi infix:<∈&gt; ( $a, Complement:D $c ) { $a ∉ $c.set   }
multi infix:<∉&gt; ( $a, Complement:D $c ) { $a ∈ $c.set }

my $set = (1, 2, 3).Set;
my $c = Complement.new: set => $set;

put 3 ∈ $set;
put 4 ∈ $c;

根据我infix:<∉&gt;对另一个的定义,更一般的定义似乎已经消失了。没有其他候选人:

True
Cannot resolve caller infix:<∉&gt;(Int, Set); none of these signatures match:
    ($a, Complement:D $c)
  in sub infix:<∈&gt; at /Users/brian/Desktop/complement.p6 line 11
  in block <unit> at /Users/brian/Desktop/complement.p6 line 18

我需要做些什么来保留具有不同签名的先前定义?

4

1 回答 1

14

这是因为&infix:<∈&gt;是一个多,而&infix:<∉&gt;不是:

$ perl6 -e '&infix:<∈&gt;.candidates.head.multi.say'
True
$ perl6 -e '&infix:<∉&gt;.candidates.head.multi.say'
False

当你定义你的multi &infix:<∉&gt;,你从核心阴影only &infix:<∉&gt;,这就是为什么你只看到你的候选人。

我们可能可以检测到这种情况并要求用户提供明确proto的说明以澄清他们的意思。我将其归档为R#1530。而且我会说这样的差异,即一个操作是一个multi,而另一个是一个only是具有一致核心的更大问题的一部分。我将它添加为RT#130020的评论,并在我们的D#1783文档中提到了这个问题。

您可以像这样定义您的自定义操作(如果R#1530实施了建议,则proto需要;目前不需要):

proto infix:<∉&gt; (|) {*}
multi infix:<∉&gt; ($a, Complement:D $c) { $a ∈ $c.set }
multi infix:<∉&gt; (|c) { &CORE::infix:<∉&gt;(|c) }

我只能猜测您要编写什么代码,但我想我会提到它,以便您在创作中解释它:否定的操作被定义为not A (op) B,而不是A (not(op)) B. 这种微小的差异会产生以下影响Junctions

$ perl6 -e 'say 2 ≠ 2|4'
False

如果将其定义为应用于每个操作数的否定操作,则上述将等价于 (2 ≠ 2 or 2 ≠ 4)并且始终是True,这通常不是程序员的意思,因此为什么将其计算为not (2 == 2 or 2 == 4)


回复 Jarrod 对 OP 的评论: subs(包括通过声明自定义运算符完成的语法突变)是词法的,因此如果您将声明包装到一个BEGIN块中,自定义操作将仅限于该块。

它似乎在 REPL 中起作用的原因是因为实际上存在一个错误(RT#131900),其中自定义操作在 REPL 行之间丢失,所以就像BEGIN块一样,当调用带有指向核心候选者的 args 时,自定义 multi 不再在范围内。

于 2018-02-16T13:09:56.853 回答