Normalement, si vous créez un Stream
objet, la tête sera évaluée avec impatience:
scala> Stream( {println("evaluating 1"); 1} , 2, 3)
evaluating 1
res63: scala.collection.immutable.Stream[Int] = Stream(1, ?)
Si nous créons un Stream auquel nous ajoutons dans la même instruction, il semble légèrement surprenant que la tête ne soit pas évaluée avant la concaténation. c'est à dire.
scala> 0 #:: Stream( {println("evaluating 1"); 1} , 2, 3)
res65: scala.collection.immutable.Stream[Int] = Stream(0, ?)
(#::
est associative à droite et est la méthode de ConsWrapper
, qui est une classe implicite de Stream
.)
Comment cela n'évalue-t-il pas sa tête avantavant le 0? Est-ce que le flux de queue (ou contre-cellule) n'existe pas sur le tas jusqu'à ce que nous prenions des valeurs du flux résultant? Mais si oui, comment appelons-nous #::
sur un objet qui n'existe pas encore?
Réponses:
7 pour la réponse № 1-Xprint:typer
est votre ami, chaque fois que vous voulez comprendre exactement comment un code est évalué ou des types sont déduits.
scala -Xprint:typer -e "0 #:: Stream( {println("evaluating 1"); 1} , 2, 3)"
val x$1: Int = 0;
Stream.consWrapper[Int](Stream.apply[Int]({
println("evaluating 1");
1
}, 2, 3)).#::(x$1)
Le paramètre de consWrapper
est par son nom. Donc, même cela fonctionne:
scala> (1 #:: (sys.error("!!"): Stream[Int])).head
res1: Int = 1
5 pour la réponse № 2
La tête est évaluée au moment de la création du flux.
Mais dans votre deuxième exemple, vous ne passez pas un Streem comme deuxième argument pour #::
vous passez un paramètre par nom, c'est-à-dire l'expression complète Stream( {println("evaluating 1"); 1} , 2, 3)
n'est pas évalué du tout.