Comprender método infija llamada y el operador contras (: :) en Scala
-
02-10-2019 - |
Pregunta
Soy bastante nuevo en lenguaje de programación Scala, y estaba intentando algo stucked en mi mente mientras yo estaba siguiendo las notas de la conferencia a aquí .
Creo que realmente no podía entender cómo funciona contras operador, aquí hay algunas cosas que intenté:
He creado un generador de números pseudo-aleatorios, luego trató de 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 trató de pasar lista (3) con el método nextnt. Cuando solía paratheses, no había ningún problema
scala> (gen nextInt 3) :: Nil
res69: List[Int] = List(1)
Yo tenía curiosidad acerca de la orden de ejecución, así que creé una función para comprobarlo
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. Entonces pensé que podría ser sobre la función 'nextInt', entonces intenté siguiente:
scala> 1 + 2 :: Nil
res72: List[Int] = List(3)
Además primero ejecutada, y después de que los contras se ejecuta. Así que aquí está la pregunta: ¿Cuál es la diferencia entre gen nextInt 3 :: Nil
y 1 + 2 :: Nil
Solución
Hay dos cosas de interés aquí: precedencia y fijeza . Como se mencionó sepp2k, esta pregunta desbordamiento de pila explica la precedencia, que se cree las reglas, como se cita, no son lo suficientemente completa, y no hubo cambios muy pequeños de Scala Scala 2,7 a 2,8. Las diferencias se refieren en su mayoría operadores que terminan en =
, sin embargo.
fijeza , casi todo en Scala se lee de izquierda a derecha, que es lo que los programadores están acostumbrados. En Scala, sin embargo, los operadores que terminan en :
se leen de derecha a izquierda.
Toma, pues, este ejemplo:
1 + 2 :: Nil
En primer lugar, la precedencia. Lo que tiene más precedencia, +
o :
? De acuerdo con la tabla, +
tiene prioridad sobre :
, por lo que la adición se realiza en primer lugar. Por lo tanto, la expresión es igual a este:
((1).+(2)) :: Nil
Ahora no hay conflicto precedencia, pero desde extremos ::
en :
, que tiene una fijeza diferent. Es derecho de lectura a la izquierda, por lo tanto:
Nil.::((1).+(2))
Por otro lado, en este:
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 cuyo punto el error es evidente.
PS: Estoy escribiendo (1).+(2)
en lugar de 1.+(2)
porque, en el momento de escribir estas líneas, 1.
se interpreta como un número doble, haciendo 1.+(2)
una expresión infija añadiendo el doble de 1,0 a 2. Esta sintaxis está obsoleta de Scala 2.10 0.0, y probablemente no estar presente en Scala 2.11.
Otros consejos
Se trata de no preferencia orden de ejecución. +
tiene mayor precedencia que ::
, así como análisis sintácticos a + b :: c
(a + b) :: c
. Sin embargo las llamadas a métodos infijas con nombres regulares tienen prioridad más baja, por lo a foo b c
análisis sintácticos como a foo (b c)
.
esta pregunta para obtener una lista de los operadores ordenado por su precedencia en Scala.