- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
while comprehensions ?
Sat, 2009-08-22, 22:01
Can comprehensions be created with a while ?
ex :
var i = 0;
var res = while(i < 10) yield i;
for(x <- res) println(x);
0
1
2
3
...
This example doesn't seem particularly usefull, because the for
comprehension would be just as short, but I have a case where
i want to enumerate based on a contition.
Thanks
Sun, 2009-08-23, 00:37
#2
Re: while comprehensions ?
Not really. It would be better if you asked about how to solve your particular problem. I only saw "while" used once in Scala, aside "while(true)" statements with Actors.
2009/8/22 Maxime Lévesque <maxime.levesque@gmail.com>
--
Daniel C. Sobral
Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.
2009/8/22 Maxime Lévesque <maxime.levesque@gmail.com>
Can comprehensions be created with a while ?
ex :
var i = 0;
var res = while(i < 10) yield i;
for(x <- res) println(x);
0
1
2
3
...
This example doesn't seem particularly usefull, because the for
comprehension would be just as short, but I have a case where
i want to enumerate based on a contition.
Thanks
--
Daniel C. Sobral
Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.
Sun, 2009-08-23, 02:57
#3
Re: while comprehensions ?
While-comprehensions aren't built in, probably because they don't make much sense in general.
But if you want something specific with the sort of functionality you have suggested here, I can think of two reasonable options:
(1) Extend Iterable/Iterator to take a Unit => Boolean that it calls every time in place of Iterator's hasNext; then create one of these in a for loop like normal (i.e. basically copy the strategy that Range takes, except as an unbounded rather than bounded collection). If you want it to give index numbers, have next return the index.
(2) Write a custom class that does what you want. The naming here may be somewhat inadvisable (it is generally bad form to distinguish classes and reserved words by capitalization only), but, as an example:
class While(val condition : Int=>Boolean) {
def apply[T](result : Int=>T) : Seq[T] = {
var i = 0
var L : List[T] = Nil
while (condition(i)) { L = result(i) :: L ; i+=1 }
L.reverse
}
}
object While {
def apply(condition : Int => Boolean) = new While(condition)
}
and you could then use this like so:
> While(i=>i*i < 10) (i => i*i*i)
res0: Seq[Int] = List(0, 1, 8, 27)
> While(_<5) (_+1)
res1 : Seq[Int] = List(1, 2, 3, 4, 5)
> var more = true
more: Boolean = true
> While (_=>more) (_=> { print("Stop (y/n)? ") ; val yn = System.in.read.toChar ; println(yn) ; more = (yn!='y')) ; yn })
Stop (y/n)? n
Stop (y/n)? 7
Stop (y/n)? Y
Stop (y/n)? y
res2: Seq[Char] = List(n, 7, Y, y)
The syntax is *slightly* uglier than a pure for/while construct since you need to pass functions and that can't always be done invisibly (e.g. the _=> is required in the last example). But it works pretty well if what you really want is a way to accumulate a list until a value goes false, and you need a count of iterations on the way.
(Keep in mind you need to re-set "more" to true each time you call that While loop--it's left at false on exit. Strategy (1) is better if you want to use the full set of map, foreach, for, etc..; strategy (2) lets you get exactly what you want without an extra "map" keyword.)
--Rex
2009/8/22 Maxime Lévesque <maxime.levesque@gmail.com>
But if you want something specific with the sort of functionality you have suggested here, I can think of two reasonable options:
(1) Extend Iterable/Iterator to take a Unit => Boolean that it calls every time in place of Iterator's hasNext; then create one of these in a for loop like normal (i.e. basically copy the strategy that Range takes, except as an unbounded rather than bounded collection). If you want it to give index numbers, have next return the index.
(2) Write a custom class that does what you want. The naming here may be somewhat inadvisable (it is generally bad form to distinguish classes and reserved words by capitalization only), but, as an example:
class While(val condition : Int=>Boolean) {
def apply[T](result : Int=>T) : Seq[T] = {
var i = 0
var L : List[T] = Nil
while (condition(i)) { L = result(i) :: L ; i+=1 }
L.reverse
}
}
object While {
def apply(condition : Int => Boolean) = new While(condition)
}
and you could then use this like so:
> While(i=>i*i < 10) (i => i*i*i)
res0: Seq[Int] = List(0, 1, 8, 27)
> While(_<5) (_+1)
res1 : Seq[Int] = List(1, 2, 3, 4, 5)
> var more = true
more: Boolean = true
> While (_=>more) (_=> { print("Stop (y/n)? ") ; val yn = System.in.read.toChar ; println(yn) ; more = (yn!='y')) ; yn })
Stop (y/n)? n
Stop (y/n)? 7
Stop (y/n)? Y
Stop (y/n)? y
res2: Seq[Char] = List(n, 7, Y, y)
The syntax is *slightly* uglier than a pure for/while construct since you need to pass functions and that can't always be done invisibly (e.g. the _=> is required in the last example). But it works pretty well if what you really want is a way to accumulate a list until a value goes false, and you need a count of iterations on the way.
(Keep in mind you need to re-set "more" to true each time you call that While loop--it's left at false on exit. Strategy (1) is better if you want to use the full set of map, foreach, for, etc..; strategy (2) lets you get exactly what you want without an extra "map" keyword.)
--Rex
2009/8/22 Maxime Lévesque <maxime.levesque@gmail.com>
Can comprehensions be created with a while ?
ex :
var i = 0;
var res = while(i < 10) yield i;
for(x <- res) println(x);
0
1
2
3
...
This example doesn't seem particularly usefull, because the for
comprehension would be just as short, but I have a case where
i want to enumerate based on a contition.
Thanks
Sun, 2009-08-23, 03:17
#4
Re: while comprehensions ?
p, li { white-space: pre-wrap; }It's also pretty easy to introduce the "conventional" for construct like the one in Java, but with additional "yield"-like functionality, which might give more control:
Seq[R] = {
import scala.collection.mutable.ArrayBuffer
val buffer = new ArrayBuffer[R]
while(cond) {
buffer += body
action
}
buffer.toSequence
}
var i = 0
oldfor(i = 1, i < 20, i += 2) {
println(i)
} //prints 1, 3, 5 ... 19
val ints = oldfor(i = 3, i < 30, i += 3) (i)
>ints: Seq[Int] = List(3, 6, 9, 12, 15, 18, 21, 24, 27)
> While-comprehensions aren't built in, probably because they don't make much
> sense in general.
>
> But if you want something specific with the sort of functionality you have
> suggested here, I can think of two reasonable options:
>
> (1) Extend Iterable/Iterator to take a Unit => Boolean that it calls every
> time in place of Iterator's hasNext; then create one of these in a for loop
> like normal (i.e. basically copy the strategy that Range takes, except as
> an unbounded rather than bounded collection). If you want it to give index
> numbers, have next return the index.
>
> (2) Write a custom class that does what you want. The naming here may be
> somewhat inadvisable (it is generally bad form to distinguish classes and
> reserved words by capitalization only), but, as an example:
>
> class While(val condition : Int=>Boolean) {
> def apply[T](result : Int=>T) : Seq[T] = {
> var i = 0
> var L : List[T] = Nil
> while (condition(i)) { L = result(i) :: L ; i+=1 }
> L.reverse
> }
> }
>
> object While {
> def apply(condition : Int => Boolean) = new While(condition)
> }
>
> and you could then use this like so:
> > While(i=>i*i < 10) (i => i*i*i)
>
> res0: Seq[Int] = List(0, 1, 8, 27)
>
> > While(_<5) (_+1)
>
> res1 : Seq[Int] = List(1, 2, 3, 4, 5)
>
> > var more = true
>
> more: Boolean = true
>
> > While (_=>more) (_=> { print("Stop (y/n)? ") ; val yn =
>
> System.in.read.toChar ; println(yn) ; more = (yn!='y')) ; yn })
> Stop (y/n)? n
> Stop (y/n)? 7
> Stop (y/n)? Y
> Stop (y/n)? y
> res2: Seq[Char] = List(n, 7, Y, y)
>
> The syntax is *slightly* uglier than a pure for/while construct since you
> need to pass functions and that can't always be done invisibly (e.g. the
> _=> is required in the last example). But it works pretty well if what you
> really want is a way to accumulate a list until a value goes false, and you
> need a count of iterations on the way.
>
> (Keep in mind you need to re-set "more" to true each time you call that
> While loop--it's left at false on exit. Strategy (1) is better if you want
> to use the full set of map, foreach, for, etc..; strategy (2) lets you get
> exactly what you want without an extra "map" keyword.)
>
> --Rex
>
>
> 2009/8/22 Maxime Lévesque <maxime.levesque@gmail.com>
>
> > Can comprehensions be created with a while ?
> > ex :
> > var i = 0;
> > var res = while(i < 10) yield i;
> >
> > for(x <- res) println(x);
> > 0
> > 1
> > 2
> > 3
> > ...
> >
> > This example doesn't seem particularly usefull, because the for
> > comprehension would be just as short, but I have a case where
> > i want to enumerate based on a contition.
> >
> > Thanks
david.flemstrom@gmail.com
Seq[R] = {
import scala.collection.mutable.ArrayBuffer
val buffer = new ArrayBuffer[R]
while(cond) {
buffer += body
action
}
buffer.toSequence
}
var i = 0
oldfor(i = 1, i < 20, i += 2) {
println(i)
} //prints 1, 3, 5 ... 19
val ints = oldfor(i = 3, i < 30, i += 3) (i)
>ints: Seq[Int] = List(3, 6, 9, 12, 15, 18, 21, 24, 27)
> While-comprehensions aren't built in, probably because they don't make much
> sense in general.
>
> But if you want something specific with the sort of functionality you have
> suggested here, I can think of two reasonable options:
>
> (1) Extend Iterable/Iterator to take a Unit => Boolean that it calls every
> time in place of Iterator's hasNext; then create one of these in a for loop
> like normal (i.e. basically copy the strategy that Range takes, except as
> an unbounded rather than bounded collection). If you want it to give index
> numbers, have next return the index.
>
> (2) Write a custom class that does what you want. The naming here may be
> somewhat inadvisable (it is generally bad form to distinguish classes and
> reserved words by capitalization only), but, as an example:
>
> class While(val condition : Int=>Boolean) {
> def apply[T](result : Int=>T) : Seq[T] = {
> var i = 0
> var L : List[T] = Nil
> while (condition(i)) { L = result(i) :: L ; i+=1 }
> L.reverse
> }
> }
>
> object While {
> def apply(condition : Int => Boolean) = new While(condition)
> }
>
> and you could then use this like so:
> > While(i=>i*i < 10) (i => i*i*i)
>
> res0: Seq[Int] = List(0, 1, 8, 27)
>
> > While(_<5) (_+1)
>
> res1 : Seq[Int] = List(1, 2, 3, 4, 5)
>
> > var more = true
>
> more: Boolean = true
>
> > While (_=>more) (_=> { print("Stop (y/n)? ") ; val yn =
>
> System.in.read.toChar ; println(yn) ; more = (yn!='y')) ; yn })
> Stop (y/n)? n
> Stop (y/n)? 7
> Stop (y/n)? Y
> Stop (y/n)? y
> res2: Seq[Char] = List(n, 7, Y, y)
>
> The syntax is *slightly* uglier than a pure for/while construct since you
> need to pass functions and that can't always be done invisibly (e.g. the
> _=> is required in the last example). But it works pretty well if what you
> really want is a way to accumulate a list until a value goes false, and you
> need a count of iterations on the way.
>
> (Keep in mind you need to re-set "more" to true each time you call that
> While loop--it's left at false on exit. Strategy (1) is better if you want
> to use the full set of map, foreach, for, etc..; strategy (2) lets you get
> exactly what you want without an extra "map" keyword.)
>
> --Rex
>
>
> 2009/8/22 Maxime Lévesque <maxime.levesque@gmail.com>
>
> > Can comprehensions be created with a while ?
> > ex :
> > var i = 0;
> > var res = while(i < 10) yield i;
> >
> > for(x <- res) println(x);
> > 0
> > 1
> > 2
> > 3
> > ...
> >
> > This example doesn't seem particularly usefull, because the for
> > comprehension would be just as short, but I have a case where
> > i want to enumerate based on a contition.
> >
> > Thanks
david.flemstrom@gmail.com
> Can comprehensions be created with a while ?
> ex :
> var i = 0;
> var res = while(i < 10) yield i;
>
> for(x <- res) println(x);
> 0
> 1
> 2
> 3
> ...
>
> This example doesn't seem particularly usefull, because the for
> comprehension would be just as short, but I have a case where
> i want to enumerate based on a contition.
>
> Thanks
In the above example, how should the compiler know that it has to increase i each time? It doesn't make any sense to me.
If you want to have values in a range, do the following:
val i = 10val res = 0 until i
for(x <- res) println(x) //or: res.foreach(println)
>0
>1
>2
>3
> ...
>9
If you instead say:val res = 0 to 10 //note: to
...the range will include 10 too.
David Flemströmdavid.flemstrom@gmail.com