I'm playing with this little thing where a set can act as its complement by flipping around the tests. In order to make that work, I create special versions of the membership operators.
class Complement {
has $.set;
}
multi infix:<∈> ( $a, Complement:D $c ) { $a ∉ $c.set }
multi infix:<∉> ( $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;
With my definition of infix:<∉> the other, more general one seems to have disappeared. There are no other candidates:
True
Cannot resolve caller infix:<∉>(Int, Set); none of these signatures match:
($a, Complement:D $c)
in sub infix:<∈> at /Users/brian/Desktop/complement.p6 line 11
in block <unit> at /Users/brian/Desktop/complement.p6 line 18
What do I need to do to retain previous definitions with different signatures?
This is because
&infix:<∈>is a multi, while&infix:<∉>is not:When you defined your
multi &infix:<∉>, you shadowedonly &infix:<∉>from core, and that's why you see only your candidate.We can probably detect such a situation and require the user to provide explicit
prototo clarify what they meant. I filed that as R#1530. And I'd say such differences that one op is amultiwhile another is anonlyis part of a larger issue of having consistent core; I added it as a comment on RT#130020 and mentioned the problem in our docs on D#1783.You could define your custom op like so (if the suggestion in
R#1530is implemented, theprotowould be required; currently it isn't):I can only guess what you're trying to code, but thought I'd mention it, for you to account for it in your creation: negated ops are defined as
not A (op) B, notA (not(op)) B. This small difference has impact when it comes toJunctions:If it were defined as a negated op applied to each operand, the above would be equivalent to (
2 ≠ 2 or 2 ≠ 4)and would always beTrue, which is often not what the programmer would've meant, hence why it's instead computed asnot (2 == 2 or 2 == 4)To reply to Jarrod's comments on OP: subs (including grammar mutations done by declaring custom operators) are lexical, so if you wrapped the declaration into a
BEGINblock, the custom op will be scoped to just that block.And the reason it appeared to work in REPL is because there's actually a bug (RT#131900) where custom ops are lost between REPL lines, so just as with the
BEGINblock, by the time the call came with args destined to the core candidates, the custom multi was no longer in scope.