2016-10-21 4 views
0

J'essaye d'écrire dans Scala une fonction similaire à la fonction "itérer" de Haskell. Compte tenu d'une valeur x et une fonction f, itérer doit retourner un flux composé des valeurs x, f (x), f (f (x)), etc ...Scala fonction itérée infinie

Voici le code que j'ai écrit:

object current { 
    def iterate[A](f: A => A, x: A): Stream[A] = { 
    val res: Stream[A] = x #:: res.map(f) 
    return res 
    } 

    def double(x: Int) = x * 2 

    def main(args: Array[String]): Unit = { 
    val str: Stream[Int] = iterate(double, 2) 
    } 
} 

Lorsque je tente de le compiler, je reçois l'erreur:

référence avant extension de la définition de la résolution de valeur (à la ligne 3)

Comment puis-je corriger mon code pour générer le bon flux ?

+0

http://stackoverflow.com/questions/35111887/scala-error-forward-reference-extends-over- definition-of-value-when-code-appe –

Répondre

3

Je suppose que vous besoin de quelque chose comme ceci:

def iterate[A](f: A => A, x: A): Stream[A] = x #:: iterate(f, f(x)) 

mais pour une meilleure inférence de type, je l'écrire de cette façon:

def iterate[A](x: A)(f: A => A): Stream[A] = x #:: iterate(f(x))(f) 

scala> iterate(0)(_ + 1).take(10).force 
res0: scala.collection.immutable.Stream[Int] = Stream(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 
1

Je pense que c'est ce que vous recherchez.

def iterate[A](f: A => A, x: A): Stream[A] = Stream.iterate[A](x)(f) 

Maintenant vous pouvez l'utiliser comme ceci.

def double(x: Int): Int = x * 2 

def main(args: Array[String]): Unit = { 
    val str: Stream[Int] = iterate(double, 2).take(10) 
    str.foreach(print) 
} 
+0

J'ai essayé votre solution, mais j'ai seulement ce message d'erreur: value iterate n'est pas membre de l'objet Stream – vkubicki

+0

Etes-vous sûr? Voici cette méthode. https://github.com/scala/scala/blob/v2.11.8/src/library/scala/collection/immutable/Stream.scala#L1248 – Jegan

+0

Ce qui signifie que j'ai réinventé la roue. Au moins c'est proche. –

2

Merci pour les deux réponses. Le changement minimal à mon code de la fonction itérer au travail est tout simplement d'ajouter un mot-clé paresseux:

def iterate[A](f: A => A, x: A): Stream[A] = { 
    lazy val res: Stream[A] = x #:: res.map(f) 
    return res 
}