Capire metodo infissa chiamata e contro operatore (: :) in Scala
-
02-10-2019 - |
Domanda
Sono abbastanza nuovo per il linguaggio di programmazione Scala, e stava cercando qualcosa stucked nella mia mente mentre seguivo le dispense a qui .
Credo che non ho potuto veramente capire come funziona contro l'operatore, qui ci sono alcune cose che ho provato:
Ho creato un generatore di numeri pseudo-casuali, poi ha cercato di creare un elenco di un valore casuale:
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
^
Ma è cercato di passare List (3) per il metodo nextnt. Quando ho usato paratheses, non c'era alcun problema
scala> (gen nextInt 3) :: Nil
res69: List[Int] = List(1)
ero curioso circa l'ordine di esecuzione, così ho creato una funzione per controllare
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)
Come visto nelle uscite, l'ordine di esecuzione è la stessa come l'ordine di visualizzazione. Poi ho pensato che potrebbe essere circa la funzione 'nextInt', poi ho provato seguente:
scala> 1 + 2 :: Nil
res72: List[Int] = List(3)
E 'inoltre prima eseguito, e dopo che contro l'esecuzione. Quindi, ecco la domanda: Qual è la differenza tra gen nextInt 3 :: Nil
e 1 + 2 :: Nil
Soluzione
Ci sono due cose di preoccupazione qui: precedenza e fissità . Come sepp2k accennato, questa domanda su Stack Overflow spiega la precedenza, il pensiero le regole, come citato, non sono abbastanza complete, e ci sono stati cambiamenti molto piccoli da Scala 2.7 a 2.8 Scala. Differenze riguardano per lo più gli operatori che terminano in =
, però.
Per quanto riguarda il fissità , quasi tutto a Scala viene letta da sinistra a destra, che è quello che i programmatori sono abituati. In Scala, tuttavia, gli operatori che terminano in :
si leggono da destra a sinistra.
Prendere, quindi, questo esempio:
1 + 2 :: Nil
In primo luogo, la precedenza. Ciò che ha la maggior parte la precedenza, +
o :
? Secondo la tabella, +
ha la precedenza su :
, quindi l'aggiunta è fatta per prima. Pertanto, l'espressione è uguale a questo:
((1).+(2)) :: Nil
Ora non c'è alcun conflitto la precedenza, ma dal momento che le estremità ::
in :
, ha una fissità spettacolo diverso. E 'proprio in lettura a sinistra, quindi:
Nil.::((1).+(2))
D'altra parte, in questo modo:
gen nextInt 3 :: Nil
Il ::
operatore ha la precedenza su nextInt
, perché :
ha la precedenza su tutte le lettere. Pertanto, e ricordando la sua fissità, diventa:
gen nextInt Nil.::(3)
che poi diventa ??p>
gen.nextInt(Nil.::(3))
A tal punto l'errore è evidente.
PS: Sto scrivendo (1).+(2)
anziché 1.+(2)
perché, al momento della scrittura, 1.
viene interpretata come un numero doppio, rendendo 1.+(2)
un'espressione infissa aggiungendo il doppio 1.0 a 2. Questa sintassi è sconsigliato di Scala 2.10 0,0, e probabilmente non essere presente su Scala 2.11.
Altri suggerimenti
Si tratta di Non la precedenza ordine di esecuzione. +
ha precedenza maggiore rispetto ::
, quindi analizza a + b :: c
come (a + b) :: c
. chiamate di metodo Tuttavia infissa con nomi regolari hanno una minore la precedenza, quindi analizza a foo b c
come a foo (b c)
.
questa domanda per un elenco degli operatori ordinato dal loro precedenza in scala.