2011-03-11 2 views
6

ici est ce que je pensais être une définition correcte et utile de fibonacci nums dans scala:Scalas (a, b) .zipped (ou) Tuple2.zipped notion en utilisant les cours d'eau/listes infinies

lazy val fibs:Stream[Int] = 0 #:: 1 #:: (fibs,fibs.tail).zipped.map(_+_) 

Cependant, Je reçois l'erreur suivante:

fibs take 10 foreach println 
0 
1 
java.lang.StackOverflowError 
    at scala.collection.mutable.LazyBuilder.(LazyBuilder.scala:25) 
    at scala.collection.immutable.Stream$StreamBuilder.(Stream.scala:492) 
    at scala.collection.immutable.Stream$.newBuilder(Stream.scala:483) 
    at... 

Je suppose que zippé ne fonctionne pas correctement avec les flux? Des suggestions sur la façon de faire ce travail, ou pourquoi cela ne fonctionne pas (ne devrait pas?)?

+0

J'allais juste poser cette question _exact_. Cool de savoir que quelqu'un est arrivé avant moi. +1 – KChaloux

Répondre

8

Les travaux suivants correctement

val fibs:Stream[Int] = 0 #:: 1 #:: (fibs zip fibs.tail).map{ case (a,b) => a+b } 

Le problème avec Tuple2.zipped est qu'il suppose qu'il peut fonctionner sur des séquences foreach il est passer comme un éclair. C'est probablement à cause de la conception, car faire les choses de la façon dont Stream.zip implémente cela vous donnerait probablement de mauvaises performances pour toute longueur finie Seq qui n'est pas List ou Stream. (Parce que la plupart des structures de données ne prennent pas en charge une mise en œuvre efficace de tail.)


Stream.zip est essentiellement mis en œuvre comme suit (bien qu'il fait des trucs pour rendre les types plus général).

class Stream[A]{ 
    def zip(other:Stream[B]) = 
    (this.head, other.head) #:: (this.tail zip other.tail) 
} 
+0

Bien que le qualificatif paresseux dans votre question ne soit pas nécessaire, je vous assure que le supprimer dans ma réponse n'était pas ce qui a fait ce travail. –

+0

Ok, ce que vous avez montré est très sympa :) Je suppose que cela ne fait que montrer combien nous avons besoin d'un "zipWith" qui prend une fonction 2-arity comme un argument comme dans haskell. Je ne comprends vraiment pas pourquoi ce n'est pas là à Scala? – Felix

+1

@Fixix: Je ne vois pas comment 'zipWith' pourrait aider. 'zipWith' sur un tuple serait toujours implémenté comme un' foreach' qui déborderait lorsque la première liste serait un flux infini. –

3

Il y a un billet à ce sujet dans la base de données Trac Scala: http://lampsvn.epfl.ch/trac/scala/ticket/2634

Le billet a été fermé comme wontfix, mais notez Adriaan de « Ou nous manque quelque chose? » dans les commentaires - peut-être cela sera revisité un jour.

Questions connexes