list - documentacion - Entendiendo el método infijo llamada y operador de contras(::) en Scala
scala doc (2)
Hay dos cosas de interés aquí: la precedence y la fixity . Como lo mencionó sepp2k, esta pregunta en Stack Overflow explica la precedencia, pensaba que las reglas, tal como se citan, no están lo suficientemente completas, y hubo cambios muy pequeños de Scala 2.7 a Scala 2.8. Sin embargo, las diferencias se refieren principalmente a operadores que terminan en =
.
En cuanto a la fijeza , casi todo en Scala se lee de izquierda a derecha, que es a lo que están acostumbrados los programadores. En Scala, sin embargo, los operadores que terminan en :
se leen de derecha a izquierda.
Tomemos, pues, este ejemplo:
1 + 2 :: Nil
Primero, la precedencia. ¿Qué tiene más precedencia, +
o:? De acuerdo con la tabla, +
tiene prioridad sobre :
por lo que la adición se realiza primero. Por lo tanto, la expresión es igual a esto:
((1).+(2)) :: Nil
Ahora no hay conflicto de precedencia, pero como ::
termina en :
tiene una fijación diferente. Se lee de derecha a izquierda, por lo tanto:
Nil.::((1).+(2))
Por otro lado, en esto:
gen nextInt 3 :: Nil
El operador ::
tiene prioridad sobre nextInt
, porque :
tiene prioridad sobre todas las letras. Por lo tanto, y recordando su fijeza, se convierte en:
gen nextInt Nil.::(3)
Que luego se convierte
gen.nextInt(Nil.::(3))
En qué punto el error es obvio.
PS: Estoy escribiendo (1).+(2)
lugar de 1.+(2)
porque, en el momento de escribir esto, 1.
se interpreta como un número doble, lo que hace que 1.+(2)
una expresión de infijo. agregando el doble 1.0 a 2. Esta sintaxis está en desuso a partir de Scala 2.10.0, y probablemente no estará presente en Scala 2.11.
Soy bastante nuevo en el lenguaje de programación Scala, y estaba probando algo atascado en mi mente mientras seguía las notas de la clase here .
Creo que realmente no pude entender cómo funcionan los operadores contras, aquí hay algunas cosas que probé:
He creado un generador de números pseudoaleatorios y luego he intentado crear una lista de un valor aleatorio:
scala> val gen = new java.util.Random
gen: java.util.Random = java.util.Random@1b27332
scala> gen nextInt 3 :: Nil
<console>:7: error: type mismatch;
found : List[Int]
required: Int
gen nextInt 3 :: Nil
^
Pero intentó pasar la Lista (3) al método nextnt. Cuando usé paratheses, no hubo problema
scala> (gen nextInt 3) :: Nil
res69: List[Int] = List(1)
Tenía curiosidad por el orden de ejecución, así que creé una función para verificarlo
scala> def pr(i:Int):Int = { println(i); i }
pr: (i: Int)Int
scala> pr(1) :: pr(2) :: pr(3) :: Nil
1
2
3
res71: List[Int] = List(1, 2, 3)
Como se ve en las salidas, el orden de ejecución es el mismo que el orden de aparición. Luego pensé que podría tratarse de la función ''nextInt'', luego intenté lo siguiente:
scala> 1 + 2 :: Nil
res72: List[Int] = List(3)
Primero ejecutó la suma, y luego se ejecutan los contras. Entonces, aquí está la pregunta: ¿Cuál es la diferencia entre gen nextInt 3 :: Nil
y 1 + 2 :: Nil
?
Se trata de la precedencia, no del orden de ejecución. +
tiene mayor prioridad que ::
, por lo que a + b :: c
analiza como (a + b) :: c
. Sin embargo, las llamadas al método infijo con nombres regulares tienen una prioridad menor, por lo que a foo bc
analiza como a foo (bc)
.
Consulte esta pregunta para obtener una lista de operadores ordenados por su prioridad en scala.