Не могу перегрузить логические операторы (или, и) для моего класса - PullRequest
15 голосов
/ 08 июля 2019

Я пытался перегрузить логический оператор or для пользовательского класса, но, похоже, он не работает.Вот что я делаю:

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

Я ожидаю получить works!(1, 2) в качестве вывода, но вместо этого я получаю A.new(a => 1), что является результатом стандартного оператора or.

Другие операторы (кроме and и xor), похоже, работают для меня:

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

приводит к works!(1, 2).

Я делаю что-то неправильно илипросто нет способа перегрузить стандартные операторы or, and, xor?

1 Ответ

15 голосов
/ 08 июля 2019

Только операторы, которые компилируются в вызов подпрограммы, могут быть перегружены. Поскольку вызовы подпрограмм оценивают свои аргументы перед выполнением вызова, те операторы, которые требуют отложенной оценки одного из своих операндов, обрабатываются как специальные формы в компиляторе.

Логические операторы, такие как and, or, && и ||, указываются как вычисляющие только их второй операнд в зависимости от достоверности их первого операнда, и поэтому не могут быть скомпилированы в вызовы подпрограммы .

Даже если бы они должны были скомпилироваться в вызов подпрограммы, который отбросил второй операнд, многократная диспетчеризация, как написано в вопросе, все равно была бы невозможна для типа второго аргумента, так как семантика этих операторов означает, что мы можем ' Мы не можем оценить его сразу, но это, в свою очередь, означает, что мы не можем найти его тип для отправки.

...