/ / Quand la tête d'un flux est-elle évaluée exactement? - scala, stream, évaluation paresseuse

Quand exactement la tête d'un flux est-elle évaluée? - scala, stream, paresseux-evaluation

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.