Discussion:
For comprehension and LazyList
Eric Torreborre
2007-06-21 00:15:57 UTC
Permalink
Hi,

I am new to Scala and I am just starting playing with it.

I find for-comprehensions very useful to generate combinatorial data in a
single statement, however I would like to know what the idiomatic way in
scala to use this generation either as a List or as a LazyList.

I understand that:

for (d <- days; w <- weeks) yield s + "." + w

returns a List[String]. But what if I find that there are too many values
and I prefer to consume them as in a LazyList. Is there a way to do that
without modifying my for-comprehension code?

Thanks,

Eric
--
View this message in context: http://www.nabble.com/For-comprehension-and-LazyList-tf3955830.html#a11224658
Sent from the Scala mailing list archive at Nabble.com.
martin odersky
2007-06-21 09:41:55 UTC
Permalink
Post by Eric Torreborre
Hi,
I am new to Scala and I am just starting playing with it.
I find for-comprehensions very useful to generate combinatorial data in a
single statement, however I would like to know what the idiomatic way in
scala to use this generation either as a List or as a LazyList.
for (d <- days; w <- weeks) yield s + "." + w
returns a List[String]. But what if I find that there are too many values
and I prefer to consume them as in a LazyList. Is there a way to do that
without modifying my for-comprehension code?
Good point. I think there should be a method that converts a List (or
any Iterable) to a Stream. With such a method you could write:

for (d <- days.toStream; w <- weeks) yield s + "." + w

For now, you need to write your own conversion from lists to streams. I.e., like

def list2stream[T](xs: List[T]) = Stream.fromIterator(xs.elements)

and apply it as follows:

for (d <- list2stream(days); w <- weeks) yield s + "." + w

Note that there is no need to convert weeks to a stream. In a for
comprhension, it is the first generator which decides on what type the
computation is performed. If the first generator is a stream, all
operations will be done lazily.

Hope this helps

-- Martin
Eric Torreborre
2007-06-21 10:24:20 UTC
Permalink
Thank you very much Martin,

I have now a better understanding of for comprehensions.

I hadn't realized that the map/filter transformation of for-comprehensions
implied that the first generator type determined the result. Maybe it's
worth mentioning in the next version of "ScalaByExample"?

And just for the record: there is no way that I could add this "toStream"
method to the Iterable Trait without having control over the scala library?
There's nothing here such as "open classes" as in Ruby?

If I want to add this functionality, I suppose I have to create a new class
extending the relevant Scala classes and traits and use it in my code?

I can't really make up my mind here, is it preferable that:

-I create bunches of ListUtil methods to add more functionalities to List
-I create my own List type that I reuse everywhere

I don't know what could be the "Scala way" here, but I have seen many
projects define their own utility libraries, or collection classes because
they were missing features. Some of them became eventually supported (let's
say "toStream" in that example) and the whole code base had to be modified
(most of the time it wasn't, so you ended up with a new style/old style code
base).

Since Scala is about reusability and composability, how do you think we
should deal with those "temporal" issues?

Eric.

Eric.
Post by martin odersky
Post by Eric Torreborre
Hi,
I am new to Scala and I am just starting playing with it.
I find for-comprehensions very useful to generate combinatorial data in a
single statement, however I would like to know what the idiomatic way in
scala to use this generation either as a List or as a LazyList.
for (d <- days; w <- weeks) yield s + "." + w
returns a List[String]. But what if I find that there are too many values
and I prefer to consume them as in a LazyList. Is there a way to do that
without modifying my for-comprehension code?
Good point. I think there should be a method that converts a List (or
for (d <- days.toStream; w <- weeks) yield s + "." + w
For now, you need to write your own conversion from lists to streams. I.e., like
def list2stream[T](xs: List[T]) = Stream.fromIterator(xs.elements)
for (d <- list2stream(days); w <- weeks) yield s + "." + w
Note that there is no need to convert weeks to a stream. In a for
comprhension, it is the first generator which decides on what type the
computation is performed. If the first generator is a stream, all
operations will be done lazily.
Hope this helps
-- Martin
--
View this message in context: http://www.nabble.com/For-comprehension-and-LazyList-tf3955830.html#a11230333
Sent from the Scala mailing list archive at Nabble.com.
Jon Pretty
2007-06-21 11:23:30 UTC
Permalink
Hi Eric,
Post by Eric Torreborre
And just for the record: there is no way that I could add this "toStream"
method to the Iterable Trait without having control over the scala library?
There's nothing here such as "open classes" as in Ruby?
Martin wrote a blog entry on how to do this using implicit functions a while ago. Have a look at:

http://scala.sygneca.com/patterns/pimp-my-library

Jon
--
Jon Pretty | Sygneca Ltd.
Eric Torreborre
2007-06-21 12:06:17 UTC
Permalink
Great, great, great!

This is exactly what I was looking for.

Thanks for the tip, I'm going to read the wiki thoroughly!

Eric.
Post by Jon Pretty
Hi Eric,
Post by Eric Torreborre
And just for the record: there is no way that I could add this "toStream"
method to the Iterable Trait without having control over the scala library?
There's nothing here such as "open classes" as in Ruby?
Martin wrote a blog entry on how to do this using implicit functions a
http://scala.sygneca.com/patterns/pimp-my-library
Jon
--
Jon Pretty | Sygneca Ltd.
--
View this message in context: http://www.nabble.com/For-comprehension-and-LazyList-tf3955830.html#a11231732
Sent from the Scala mailing list archive at Nabble.com.
Loading...