Non-strict view of scanLeft - scala

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.

Related

How can I use a Scala List as a Stack?

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)

Is it possible to elude the Scala's messy ways of handling tuples as input parameters with Scalaz?

I want to do something like this List(1 -> 2, 4 -> 5).map(_ + _) to get List(3, 9) as a result. But it doesn't work that way.
Does Scalaz provide means to deal with this in a convenient way, unlike the Scala's native "tupled" or pattern matching?
Scalaz won't help you.
You can use plain Scala with the answer of #tylerweir (I really like this solution) :
scala> val a = List(1 -> 2, 4 -> 5).map(x => x._1 + x._2)
a: List[Int] = List(3, 9)
OR you can do a more "generic" stuff (it works on any tupple "size") :
scala> val a = List(1 -> 2, 4 -> 5, (1,2,3)).map(_.productElements.
collect{case i:Int => i}.sum)
a:List[Int] = List(3,9,6)
OR you can use Shapeless (from Miles Sabin : https://github.com/milessabin/shapeless) :
scala> val a = List(1 -> 2, 4 -> 4).map(_.hlisted.toList.sum)
I actually think the following is exceptionally convenient—even better than the pattern matching versions in the other answers:
List(1 -> 2, 4 -> 5) map Function.tupled(_ + _)
But I'll be perverse and provide a Scalaz solution to a slightly different problem. Suppose we're working with streams instead of lists, and also suppose we built our stream of pairs by zipping the following two streams:
val a = Stream(1, 4)
val b = Stream(2, 5)
Scalaz includes an instance of what's called the "zip list" applicative functor for streams. It's not the default instance, but we can "tag" our streams appropriately and use it like this:
scala> import scalaz._, std.stream._
import scalaz._
import std.stream._
scala> streamZipApplicative(Tags.Zip(a), Tags.Zip(b))(_ + _).toList
res0: List[Int] = List(3, 9)
And there you go! A Scalaz solution to a vaguely related problem. (I'm only being a little sarcastic—I love this stuff, and the zip list applicative functor is worth knowing about.)
Do you need something more general than this?
scala> val a = List(1 -> 2, 4 -> 5).map(x => x._1 + x._2)
a: List[Int] = List(3, 9)
Using a small productivity library embrace it is possible to do that like so:
List(1 -> 2, 4 -> 5).map(_ $$ (_ + _))
If you want to use scalaz to do this, then you are probably looking to do this with Lenses.
See the course Learning scalaz: Day 11, and also the lecture by Edward Kmett Lenses a Functional Imperative captured on video. On page 42 of the pdf slides Edward explains the use of Lenses with Maps to change them purely functionally.

Scala: Yielding from one type of collection to another

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

What is the difference between the methods iterator and view?

scala> (1 to 10).iterator.map{_ * 2}.toList
res1: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
scala> (1 to 10).view.map{_ * 2}.force
res2: Seq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
Other than using next,hasNext, when should I choose iterator over view or view over iterator?
There's a huge difference between iterators and views. Iterators are use once only, compute on demand, while views are use multiple times, recompute each time, but only the elements needed. For instance:
scala> val list = List(1,2,3).map{x => println(x); x * 2}
1
2
3
list: List[Int] = List(2, 4, 6)
scala> list(2)
res14: Int = 6
scala> list(2)
res15: Int = 6
scala> val view = List(1,2,3).view.map{x => println(x); x * 2}
view: scala.collection.SeqView[Int,Seq[_]] = SeqViewM(...)
scala> view(2)
3
res12: Int = 6
scala> view(2)
3
res13: Int = 6
scala> val iterator = List(1,2,3).iterator.map{x => println(x); x * 2}
iterator: Iterator[Int] = non-empty iterator
scala> iterator.drop(2).next
1
2
3
res16: Int = 6
scala> iterator.drop(2).next
[Iterator.next] (Iterator.scala:29)
(access lastException for the full trace)
view produces a lazy collection/stream. It's main charm is that it won't try and build the whole collection. This could prevent a OutOfMemoryError or improve performance when you only need the first few items in the collection. iterator makes no such guarantee.
One more thing. At least on Range, view returns a SeqView, which is a sub-type of Seq, so you can go back or start again from the beginning and do all that fun sequency stuff.
I guess the difference between an iterator and a view is a matter of in-front and behind. Iterators are expected to release what has been seen. Once next has been called, the previous is, hopefully, let go. Views are the converse. They promise to not acquire what has not been requested. If you have a view of all prime numbers, an infinite set, it has only acquired those primes you've asked for. It you wanted the 100th, 101 shouldn't be taking up memory yet.
This page talks about when to use views.
In summary, views are a powerful tool to reconcile concerns of
efficiency with concerns of modularity. But in order not to be
entangled in aspects of delayed evaluation, you should restrict views
to two scenarios. Either you apply views in purely functional code
where collection transformations do not have side effects. Or you
apply them over mutable collections where all modifications are done
explicitly. What's best avoided is a mixture of views and operations
that create new collections while also having side effects.

Scala: Producing the intermediate results of a fold

I've come across the problem of maintaining a state throughout a map operation several times. Imagine the following task:
Given a List[Int], map each element to the sum of all preceding elements and itself.
So 1,2,3 becomes 1, 1+2, 1+2+3.
One solution I've come up with is:
scala> val a = 1 to 5
a: scala.collection.immutable.Range.Inclusive with scala.collection.immutable.Range.ByOne = Range(1, 2, 3, 4, 5)
scala> a.foldLeft(List(0)){ case (l,i) => (l.head + i) :: l }.reverse
res3: List[Int] = List(0, 1, 3, 6, 10, 15)
But somehow I feel that there has to be a simpler solution.
You're trying to compute the sequence of partial sums.
The general operation for computing such accumulations is not fold but scan, though scan is expressible through fold in the way you showed (and fold is actually the last element of the list produced by scan).
scala> List(1,2,3).scanLeft(0)(_ + _)
res26: List[Int] = List(0, 1, 3, 6)
#Dario gave the answer, but just to add that the scala library provides scanLeft:
scala> List(1,2,3).scanLeft(0)(_ + _)
res26: List[Int] = List(0, 1, 3, 6)
The scan answers are the best ones, but it's worth noting that one can make the fold look nicer and/or be shorter than in your question. First, you don't need to use pattern matching:
a.foldLeft(List(0)){ (l,i) => (l.head + i) :: l }.reverse
Second, note that foldLeft has an abbreviation:
(List(0) /: a){ (l,i) => (l.head + i) :: l }.reverse
Third, note that you can, if you want, use a collection that can append efficiently so that you don't need to reverse:
(Vector(0) /: a){ (v,i) => v :+ (v.last + i) }
So while this isn't nearly as compact as scanLeft:
a.scanLeft(0)(_ + _)
it's still not too bad.
I like to fold around just like everybody else, but a less FP answer is very concise and readable:
a.map{var v=0; x=>{v+=x; v}}