Design for collections upgrades
Craig P. Motlin
motlin at gmail.com
Mon Mar 14 18:20:16 PDT 2011
Here's what happens in Scala if you mutate after iterating through the
Stream.
scala> import scala.collection.mutable._
scala> val buffer = new ArrayBuffer[Int]
scala> buffer ++= List(1, 2, 3)
scala> val stream = buffer.toStream
stream: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> stream.toString
res2: String = Stream(1, ?)
scala> stream.foreach(println)
1
2
3
scala> stream.toString
res4: String = Stream(1, 2, 3)
scala> buffer.remove(0)
res5: Int = 1
scala> stream.toString
res6: String = Stream(1, 2, 3)
And here's what happens if you mutate before the Stream has a chance to
fully memoize.
scala> val stream2 = buffer.toStream
stream2: scala.collection.immutable.Stream[Int] = Stream(2, ?)
scala> buffer.remove(0)
res7: Int = 2
scala> stream2.toString
res8: String = Stream(2, ?)
scala> stream2.foreach(println)
2
java.lang.IndexOutOfBoundsException: 1
at
scala.collection.mutable.ResizableArray$class.apply(ResizableArray.scala:45)
at scala.collection.mutable.ArrayBuffer.apply(ArrayBuffer.scala:43)
at
scala.collection.IndexedSeqLike$Elements.next(IndexedSeqLike.scala:59)
at scala.collection.Iterator$class.toStream(Iterator.scala:1011)
at
scala.collection.IndexedSeqLike$Elements.toStream(IndexedSeqLike.scala:52)
at
scala.collection.Iterator$$anonfun$toStream$1.apply(Iterator.scala:1011)
at
scala.collection.Iterator$$anonfun$toStream$1.apply(Iterator.scala:1011)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:565)
at scala.collection.immutable.Stream$Cons.tail(Stream.scala:557)
at scala.collection.immutable.Stream.foreach(Stream.scala:261)
at .<init>(<console>:11)
at .<clinit...
On Mon, Mar 14, 2011 at 11:41 AM, Rémi Forax <forax at univ-mlv.fr> wrote:
> On 03/14/2011 04:41 PM, Craig P. Motlin wrote:
>
> In the Scalable implementation, both println statements print the same
> thing. Yes that's confusing, but its very similar to mutating a collection
> while working with lazy evaluation.
>
>
> No, in Java you will get a fail fast ConcurrentModificationException
> if you mutate during a lazy evaluation.
>
> Rémi
>
>
> On Mar 14, 2011 10:39 AM, "Rémi Forax" <forax at univ-mlv.fr> wrote:
> > On 03/14/2011 02:30 PM, Craig P. Motlin wrote:
> >> There are two forms of lazy evaluation and I see people using the same
> term
> >> (Stream) to refer to both. In Scala they are called view and stream and
> I
> >> was confused about the difference so I asked on Stack Overflow.
> Basically
> >> the difference is:
> >> In a view elements are recomputed each time they are accessed. In a
> stream
> >> elements are retained as they are evaluated.
> >>
> >> I think that Java collections ought to support both, which is another
> reason
> >> I think that eager ought to be the default. See the full explanation
> here:
> >>
> http://stackoverflow.com/questions/2282754/what-is-the-difference-between-a-view-and-a-stream
> >
> > Interresting.
> > But memoization is hard to provide when your original collection is
> mutable:
> >
> > What does this code print ?
> >
> > LinkedList<Integer> list = new LinkedList<>();
> > Collections.addAll(list, 1, 2, 3, 4, 5);
> > List<Integer> list2 = list.asScalaStreamPlease();
> > System.out.println(list2.join(" ")); // the whole list is now memoized
> >
> > list.remove(0); // wink wink
> > System.out.println(list2.join(" "));
> >
> > Rémi
> >
> >
>
>
>
More information about the lambda-dev
mailing list