I'm migrating a project from Scala 2.12.1 to 2.13.6, and find that SeqView#flatMap
now returns a View
, which doesn't have a distinct
method. I thus have one bit of code that does not compile anymore:
val nodes = debts.view
.flatMap { case Debt(from, to, _) => List(from, to) }
.distinct
.map(name => (name, new Node(name)))
.toMap
There's a dumb way to fix it, by converting the view to a seq and then back to a view:
val nodes = debts.view
.flatMap { case Debt(from, to, _) => List(from, to) }.toSeq.view
.distinct
.map(name => (name, new Node(name)))
.toMap
However, this is obviously not great because it forces the view to be collected, and also it's just super inelegant to have to go back-and-forth between types. I found another way to fix it, with is to use a LazyList
:
val nodes = debts.to(LazyList)
.flatMap { case Debt(from, to, _) => List(from, to) }
.distinct
.map(name => (name, new Node(name)))
.toMap
Now that's what I want, it basically behaves like a Java stream. Sure, some operations have O(n)
memory usage like distinct
, but at least all operations after it get to be streamed, without reconstructing the data structure.
With this, it gets me thinking about why we should ever need a view, given that they're much less powerful than before (even if I can believe 2.13 has fixed some other issues this power was introducing). I looked for the answer and found hints, but nothing that I found comprehensive enough. Below is my research:
- Description of views in 2.13
- StackOverflow: What is the difference between List.view and LazyList?
- Another comparison on an external website
It might be me, but even after reading these references, I don't find a clear upside in using views, for most if not all use cases. Anyone more enlightened than me?