Подтвердить что ты не робот

Почему префикс `unary_` необходим в scala?

Начинающий Scala вопрос, но я не смог найти ответ здесь.

Как и при перегрузке в С++, я ожидал, что компилятор сможет определить разницу между методом -, который принимает один параметр (с тем же типом, что и класс) и унарная версия -, которая не принимает параметров, так зачем нужен unary_?

4b9b3361

Ответ 1

Префикс unary_ для унарных префиксных операторов немного вводит в заблуждение: это больше о префиксной части, чем одинарная часть. Вам нужно каким-то образом отличить

!foo // unary prefix !

из

foo! // unary postfix !

Помните: Scala фактически не имеет операторов. Существует два способа вызова метода с помощью . или с пробелом:

foo.bar(1, "two")
foo bar(1, "two")

И когда у вас есть один аргумент, вы можете оставить круглые скобки:

foo plus(1)
foo plus 1

Наконец, (почти) любой символ является законным в идентификаторе:

foo plus 1
foo + 1

Теперь похоже, что Scala имеет двоичный инфикс +, но на самом деле это не так. Это просто обычный метод, вызванный с помощью обычного синтаксиса вызова метода.

Однако, что я сказал выше, не совсем верно. Если Scala не поддерживала операторов, и все это был обычный вызов метода, тогда

2 + 3 * 4

будет оцениваться до 20 (например, в Smalltalk, Self и Newspeak, например) вместо 14. Таким образом, есть немного поддержки для операторов в Scala (на самом деле два маленьких бита). Когда метод вызывается с пробелом (так называемый "синтаксис оператора" ) вместо ., и этот метод начинается с символа оператора, тогда Scala будет соблюдать приоритет оператора.

И другая небольшая поддержка оператора - это то, что есть некоторые операторы, которые вы хотели бы иметь, но это не может быть легко выражено как вызов метода. Он отлично работает для двоичных инфиксных операторов и унарных операторов постфикса:

foo op bar // same as:
foo.op(bar)

foo op     // same as:
foo.op

Но не для операторов префикса или "around-fix":

!foo
foo(bar)

Итак, существует несколько специальных правил синтаксического перевода сахара:

!foo
foo.unary_!
// same for +, - and ~

foo(bar)
foo.apply(bar)

foo(bar) = 1
foo.update(bar, 1)

foo += 1
foo.+=(1) // but if this doesn't compile, then the compiler will also try
foo = foo.+(1)

И причина, по которой должно быть подчеркивание между буквенно-цифровой и "операторной" частью в имени метода, заключается в том, что вы не знаете,

foo!

означает

foo.!

или

this.foo!

Таким образом, foo! как имя метода является незаконным, его нужно называть foo_!.

Ответ 2

Потому что в scala вполне нормально создавать метод с именем -, который не принимает аргументов. Как бы вы различали нормальный и унарный метод? Например, ! имеет совершенно другое значение как унарное, чем как оператор post fix.