The question Why does my takeWhile fail to work with my Stream makes it clear that takeWhile() is lazy:
Stream.from(1).takeWhile(_ < 5) //Stream(1, ?)
But for that question the solution seemed to be that one could use toList to force evaluation as desired. But what if you want, not a list or specific value, but the continuing Stream?
It would seem that I could do it by forcing evaluation until I found the desired value and then instantiate the Stream again and use index but surely there's a better way?
UPDATE: Apparently my phrasing was confusing; I wanted the solution provided by dropWhile.
You can use span:
scala> val (before, after) = Stream.from(1).span(_ < 5)
before: scala.collection.immutable.Stream[Int] = Stream(1, ?)
after: scala.collection.immutable.Stream[Int] = Stream(5, ?)
Or, if you only care about "the continuing stream", dropWhile:
scala> val after = Stream.from(1).dropWhile(_ < 5)
after: scala.collection.immutable.Stream[Int] = Stream(5, ?)
It seems you are looking for force:
scala> val s = Stream.from(1).takeWhile(_<10)
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> s.force
res84: scala.collection.immutable.Stream[Int] = Stream(1, 2, 3, 4, 5, 6, 7, 8, 9)
It's very difficult to understand what you are asking for -- as can be seen by everyone answering a different thing. Here's the answer to another possible interpretation: you want the stream starting at a value. Well, in this case, you can do this:
scala> Stream.from(1).dropWhile(_ < 5) //Stream(1, ?)
res3: scala.collection.immutable.Stream[Int] = Stream(5, ?)
Related
It might become silly but I have question regarding to Scala Stream evaluation in immutable fashion.
Lets say I have a Stream like this (All lines executed in repl);
val a = Stream(1,2,3,4,5,6,7,8,9,10);
a: scala.collection.immutable.Stream[Int] = Stream(1, ?)
When I run following lines;
a(3);
a
I get ;
scala.collection.immutable.Stream[Int] = Stream(1, 2, 3, 4, ?)
My first question is how this immutable structure gets changed ? I mean if did like this (assuming variable 'a' defined as 'var');
a = a(3) I might expect such result.
My other question is when I run following lines;
val a = Stream(1,2,3,4,5,6,7,8,9,10);
a: scala.collection.immutable.Stream[Int] = Stream(1, ?)
val b = a;
b: scala.collection.immutable.Stream[Int] = Stream(1, ?)
b(5);
scala.collection.immutable.Stream[Int] = Stream(1, 2, 3, 4, 5, 6, ?)
a
scala.collection.immutable.Stream[Int] = Stream(1, 2, 3, 4, 5, 6, ?)
As you can see in last part after executing 'a', its seems changed again.
If I try this kind of assignment with List type (as far as I know List is strict version of Stream) and do some transformation like drop,take etc.)
val a = List(1,2,3,4,5)
val b = a;
b.dropRight(1)
variable 'a' and 'b' still is still List(1,2,3,4,5)
So how this happened and what is the point that I'm missing ?
Scala Streams provide memoization - they are like lazy lists, but once elements have been generated, they are stored for future retrieval.
So when you "force" the Stream b to evaluate some of its elements by requesting the element at index 5, the original Stream a (which is the same Stream object) is also forced.
Key point: doing this doesn't modify the stream (it remains immutable), it just changes which elements have been evaluated and are memoized.
Your Stream(1,?) and Stream(1,2,3,4,5,6,?) are the same stream, just evaluated to a different degree:
scala> val a = Stream(1,2,3,4,5,6,7,8,9,10);
a: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> val b = a
scala> a(3)
res9: Int = 4
scala> a
res10: scala.collection.immutable.Stream[Int] = Stream(1, 2, 3, 4, ?)
scala> b
res11: scala.collection.immutable.Stream[Int] = Stream(1, 2, 3, 4, ?)
scala> Stream(1,2,3,4,5,6,7,8,9,10) == a
res12: Boolean = true
scala> Stream(1,2,3,4,5,6,7,8,9,10) == b
res13: Boolean = true
I encountered a problem. scanLeft works different with an Iterator, a Stream, and a view. I'm not sure where this difference comes from.
Let's look at this example:
scala> (1 to 4).iterator.scanLeft(0)((a,b) => { println(b) ; a + b}).take(2).toList
1
2
res1: List[Int] = List(0, 1)
scala> (1 to 4).toStream.scanLeft(0)((a,b) => { println(b) ; a + b}).take(2).toList
1
res2: List[Int] = List(0, 1)
scala> (1 to 4).view.scanLeft(0)((a,b) => { println(b) ; a + b}).take(2).toList
1
2
3
4
res4: List[Int] = List(0, 1)
The strangest thing is with view. It's behaving like it was not lazy. However, when using .map, it's ok.
scala> (1 to 4).view.map{ b => println(b) ; b}.take(2).toList
1
2
res9: List[Int] = List(1, 2)
Can somebody tell me the reason?
Thanks in advance
It's a bug in views. There are many such bugs. See https://issues.scala-lang.org/browse/SI-4332 for details. (My comment of 04/Jan/2013 is me noticing the same thing you did about scanLeft.)
Because of their many quality issues, I never use views in my own code and I don't recommend them to others, either.
There is an effort underway to replace views with something better; see https://github.com/scala/slip/pull/17. In the meantime, I suggest treating them as deprecated, even though they have not been formally deprecated.
I need to create a new instance of BitSet class from another BitSet object (input).
I expected something like new BitSet(input), but none found. I could get the new instance with map() method as follows, but I don't think this is the best solution.
var r = input.map(_ + 0)(BitSet.canBuildFrom)
What's the copy constructor of BitSet? What's the general rule for copy constructor in Scala?
You can create another with the bitmask of the first:
var r = new BitSet(input.toBitMask)
I think, the general rule is to use immutable collections. They are, well, immutable, so you can pass them around freely without taking special care for copying them.
When you need mutable collections, however, copying collections becomes useful. I discovered that using standard to method works:
scala> mutable.Set(1, 2, 3)
res0: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
scala> res0.to[mutable.Set]
res1: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
scala> res0 eq res1
res2: Boolean = false
However, it won't work with BitSet because it is not a generic collection, and to needs type constructor as its generic parameter. For BitSet you can use the method suggested by Lee. BTW, it is intended exactly for scala.collection.mutable.BitSet, because scala.collection.immutable.BitSet does not contain such constructor (nor does it need it).
The "copy" method on collections is called clone (to be consistent with Java style).
scala> collection.mutable.BitSet(1,2,3)
res0: scala.collection.mutable.BitSet = BitSet(1, 2, 3)
scala> res0.clone
res1: scala.collection.mutable.BitSet = BitSet(1, 2, 3)
scala> res0 += 4
res2: res0.type = BitSet(1, 2, 3, 4)
scala> res1
res40: scala.collection.mutable.BitSet = BitSet(1, 2, 3)
I am trying to solve a hw problem in Scala. A traditional solution require a stack but stacks have not been introduced in the class so far. Only lists have been introduced. My question is how can treat a list as a stack? In other words, how can I mimic pushing and popping elements on a list?
I hope this will show the idea:
scala> val x = List(1,2,3)
x: List[Int] = List(1, 2, 3)
scala> val pushed0 = 0::x
push3: List[Int] = List(0, 1, 2, 3)
scala> val pop0 = pushed0.head
pop3: Int = 0
// it is actually more peek than fair pop
scala> val stackAfterPop = pushed0.tail
stackAfterPop: List[Int] = List(1, 2, 3)
It will actually have much better syntax when you'll be acquainted with pattern matching (next week I guess):
scala> val popped::stack = pushed0
popped: Int = 0
stack: List[Int] = List(1, 2, 3)
Concerning the yield command in Scala and the following example:
val values = Set(1, 2, 3)
val results = for {v <- values} yield (v * 2)
Can anyone explain how Scala knows which type of collection to yield into? I know it is based on values, but how would I go about writing code that replicates yield?
Is there any way for me to change the type of the collection to yield into? In the example I want results to be of type List instead of Set.
Failing this, what is the best way to convert from one collection to another? I know about _:*, but as a Set is not a Seq this does not work. The best I could find thus far is val listResults = List() ++ results.
Ps. I know the example does not following the recommended functional way (which would be to use map), but it is just an example.
The for comprehensions are translated by compiler to map/flatMap/filter calls using this scheme.
This excellent answer by Daniel answers your first question.
To change the type of result collection, you can use collection.breakout (also explained in the post I linked above.)
scala> val xs = Set(1, 2, 3)
xs: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> val ys: List[Int] = (for(x <- xs) yield 2 * x)(collection.breakOut)
ys: List[Int] = List(2, 4, 6)
You can convert a Set to a List using one of following ways:
scala> List.empty[Int] ++ xs
res0: List[Int] = List(1, 2, 3)
scala> xs.toList
res1: List[Int] = List(1, 2, 3)
Recommended read: The Architecture of Scala Collections
If you use map/flatmap/filter instead of for comprehensions, you can use scala.collection.breakOut to create a different type of collection:
scala> val result:List[Int] = values.map(2*)(scala.collection.breakOut)
result: List[Int] = List(2, 4, 6)
If you wanted to build your own collection classes (which is the closest thing to "replicating yield" that makes any sense to me), you should have a look at this tutorial.
Try this:
val values = Set(1, 2, 3)
val results = for {v <- values} yield (v * 2).toList