gmoshkin
gmoshkin

Reputation: 1135

Cannot overload logical operators (or, and) for my class

I was trying to overload the logical or operator for a custom class, but it doesn't seem to work. This is what I do:

class A { has $.a }
multi sub infix:<or> (A $a, A $b) {
    "works!({$a.a}, {$b.a})"
}
say A.new(:1a) or A.new(:2a); 

I'm expecting to get works!(1, 2) as output, but instead I get A.new(a => 1), which is the result of the standard or operator.

Other operators (except for and and xor), seem to work for me:

class A { has $.a }
multi sub infix:<anything-else> (A $a, A $b) {
    "works!({$a.a}, {$b.a})"
}
say A.new(:1a) anything-else A.new(:2a); 

results in works!(1, 2).

Am I doing something wrong or is there just no way to overload the standard or,and,xor operators?

Upvotes: 15

Views: 184

Answers (1)

Jonathan Worthington
Jonathan Worthington

Reputation: 29454

Only operators that compile into a subroutine call may be overloaded. Since subroutine calls have their arguments evaluated prior to the call being made, those operators that require delayed evaluation of one of their operands are handled as special forms in the compiler.

The logical operators, like and, or, &&, and ||, are specified as only evaluating their second operand depending on the truthiness of their first operand, and so cannot be compiled into subroutine calls.

Even if they were to compile into a subroutine call that thunked the second operand, a multiple dispatch as written in the question would still not be possible on the type of the second argument, since the semantics of these operators mean we can't evaluate it right away, but that in turn means we can't find its type in order to do the dispatch.

Upvotes: 15

Related Questions