Je suis l'exemple d'un livre pour implémenter une classe Steam en utilisant l'évaluation paresseuse dans Scala.Scala paresseux évaluation et appliquer la fonction
sealed trait Stream[+A]
case object Empty extends Stream[Nothing]
case class Cons[+A](h:() => A, t:() => Stream[A]) extends Stream[A]
object Stream {
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = {
lazy val head = hd
lazy val tail = tl
Cons(() => head,() => tail)
}
def empty[A]: Stream[A] = Empty
def apply[A](as: A*): Stream[A] = {
if (as.isEmpty) empty else cons(as.head, apply(as.tail: _*))
}
}
J'utilise une fonction simple pour tester si elle fonctionne
def printAndReturn: Int = {
println("called")
1
}
Je construis flux comme ce qui suit:
println(s"apply: ${
Stream(
printAndReturn,
printAndReturn,
printAndReturn,
printAndReturn
)
}")
La sortie est comme ceci:
called
called
called
called
apply: Cons(fpinscala.datastructures.Stream$$$Lambda$7/[email protected],fpinscala.datastructures.Stream$$$Lambda$8/[email protected])
Ensuite, je contre struits flux en utilisant cons
:
println(s"cons: ${
cons(
printAndReturn,
cons(
printAndReturn,
cons(printAndReturn, Empty)
)
)
}")
La sortie est:
cons: Cons(fpinscala.datastructures.Stream$$$Lambda$7/[email protected],fpinscala.datastructures.Stream$$$Lambda$8/[email protected])
Voici donc deux questions:
- Lors de la construction flux en utilisant la fonction appliquer, tous
printAndReturn
sont évalués. Est-ce parce que l'appel récursif àapply(as.head, ...)
évalue chaque tête? - Si la réponse à la première question est vraie, alors comment puis-je changer
apply
pour ne pas forcer l'évaluation?
Je vois maintenant. Ainsi, la solution de contournement que vous avez affichée passe une fonction qui renvoie la fonction à évaluer, de sorte que même la fonction() => est évaluée, func lui-même ne l'est pas. Est-ce correct? – KenKenKen