started software getting example scala

software - scala vs java



¿Por qué se necesita el prefijo `unary_` en scala? (2)

Pregunta de Scala para principiantes, pero no pude encontrar la respuesta aquí.

Al igual que la sobrecarga en C ++, esperaría que el compilador pueda distinguir la diferencia entre un método llamado - que toma un parámetro (con el mismo tipo que la clase) y la versión unaria de - que no tiene parámetros, ¿por qué es necesario unary_ ?


El prefijo unary_ para los operadores de prefijo unario es un poco engañoso: se trata más de la parte de prefijo que de la parte unaria . Necesitas alguna forma de distinguir

!foo // unary prefix !

desde

foo! // unary postfix !

Recuerda: Scala en realidad no tiene operadores. Hay dos formas de llamar a un método, ya sea con a . o con espacios en blanco:

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

Y cuando tiene un solo argumento, puede dejar de lado los paréntesis:

foo plus(1) foo plus 1

Por último, (casi) cualquier carácter es legal en un identificador:

foo plus 1 foo + 1

Ahora parece que Scala tiene un operador binario de infijo + , pero en realidad no lo tiene. Es solo un método normal llamado con sintaxis de llamada de método normal.

Sin embargo, lo que dije anteriormente no es del todo cierto. Si Scala no tenía soporte para operadores y todo era un método de llamada normal, entonces

2 + 3 * 4

evaluaría a 20 (como lo hace en Smalltalk, Self y Newspeak, por ejemplo) en lugar de 14. Por lo tanto, hay un poco de soporte para los operadores en Scala (dos bits, en realidad). Cuando se llama a un método con espacios en blanco (llamada "sintaxis del operador") en lugar de . , y ese método comienza con un carácter de operador, luego Scala respetará la precedencia del operador.

Y el otro poco de soporte del operador es que hay algunos operadores que le gustaría tener, pero que no pueden expresarse fácilmente como una llamada de método. Funciona bien para operadores de infijos binarios y operadores de postfix únicos:

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

Pero no para los operadores de prefijo o "alrededor de la reparación":

!foo foo(bar)

Por lo tanto, hay un par de reglas de traducción de azúcar sintácticas especiales:

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

Y la razón por la que debe haber un guión bajo entre el alfanumérico y la parte "operador" en el nombre de un método es porque no sabría si

foo!

medio

foo.!

o

this.foo!

Por lo tanto, foo! como el nombre de un método es ilegal, debe llamarse foo_! .


Porque en Scala está totalmente bien crear un método llamado - , que no tiene argumentos. ¿Cómo distinguirías entre un método normal y un método unario? Por ejemplo tiene un significado totalmente diferente como unario, que como operador de arreglos posteriores.