- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
continue keyword
Tue, 2009-03-17, 20:21
Thanks for the link. I found this post by Martin Odersky:
"Scala has a return statement which allows one to exit prematurely from a loop
within a function. It does not have break or continue, and there are no plans to add them. The reason is that (1) break and continue add significantly to language complexity without giving that much gain. (2) break and continue are most often used in large methods; in Scala it's often preferable to split these up into smaller pieces. (3) break and continue complicate specification and implementation of closures (quite a bit so)."
Well, I won't argue with that, but let me just make a couple of points.
With regard to item 3, if break and continue cause problems with closures, why not just disallow them in closures rather than disallowing them completely? (I don't even recall what a closure is, so please disregard the previous sentence if it makes no sense.)
Here's a typical case where I use "continue": I'm reading an input data file and processing each line as I read it. If the line is empty, or if it is designated as a comment, I just want to skip it and move on to the next line. With "continue", I can handle that case with one simple line and not affect the rest of the code. Without "continue," I need to add a level of indentation to the logic for processing each line. That adds a level of complexity and makes the code just a bit harder to understand, which strikes me as a bad tradeoff.
I will concede that "continue" can sometimes complicate debugging a bit, but I don't think it is any worse than an early return, which is allowed in Scala.
Russ P.
"Scala has a return statement which allows one to exit prematurely from a loop
within a function. It does not have break or continue, and there are no plans to add them. The reason is that (1) break and continue add significantly to language complexity without giving that much gain. (2) break and continue are most often used in large methods; in Scala it's often preferable to split these up into smaller pieces. (3) break and continue complicate specification and implementation of closures (quite a bit so)."
Well, I won't argue with that, but let me just make a couple of points.
With regard to item 3, if break and continue cause problems with closures, why not just disallow them in closures rather than disallowing them completely? (I don't even recall what a closure is, so please disregard the previous sentence if it makes no sense.)
Here's a typical case where I use "continue": I'm reading an input data file and processing each line as I read it. If the line is empty, or if it is designated as a comment, I just want to skip it and move on to the next line. With "continue", I can handle that case with one simple line and not affect the rest of the code. Without "continue," I need to add a level of indentation to the logic for processing each line. That adds a level of complexity and makes the code just a bit harder to understand, which strikes me as a bad tradeoff.
I will concede that "continue" can sometimes complicate debugging a bit, but I don't think it is any worse than an early return, which is allowed in Scala.
Russ P.
Tue, 2009-03-17, 21:27
#2
Re: continue keyword
On Tue, Mar 17, 2009 at 11:15 AM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote:
Thanks for the link. I found this post by Martin Odersky:
"Scala has a return statement which allows one to exit prematurely from a loop
within a function. It does not have break or continue, and there are no plans to add them. The reason is that (1) break and continue add significantly to language complexity without giving that much gain. (2) break and continue are most often used in large methods; in Scala it's often preferable to split these up into smaller pieces. (3) break and continue complicate specification and implementation of closures (quite a bit so)."
Well, I won't argue with that, but let me just make a couple of points.
With regard to item 3, if break and continue cause problems with closures, why not just disallow them in closures rather than disallowing them completely? (I don't even recall what a closure is, so please disregard the previous sentence if it makes no sense.)
Here's a typical case where I use "continue": I'm reading an input data file and processing each line as I read it. If the line is empty, or if it is designated as a comment, I just want to skip it and move on to the next line. With "continue", I can handle that case with one simple line and not affect the rest of the code. Without "continue," I need to add a level of indentation to the logic for processing each line. That adds a level of complexity and makes the code just a bit harder to understand, which strikes me as a bad tradeoff.
You've hit on the very reason that continue is bad. If you find yourself looking for the continue keyword, chances are that you should rethink your implementation. In this case, you've described a filter:
val linesToIgnore = (s: String) => s.length == 0 || isComment(s)
So, if your input is a Seq[String] called lines, you can get the lines you want to deal with:
lines.remove(linesToIgnore)
Next time you're looking for continue or break, please think about transformations rather than flow of control and I bet the answer will pop right out at you.
I will concede that "continue" can sometimes complicate debugging a bit, but I don't think it is any worse than an early return, which is allowed in Scala.
Russ P.
--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp
Tue, 2009-03-17, 22:07
#3
Re: continue keyword
2009/3/17 David Pollak <feeder [dot] of [dot] the [dot] bears [at] gmail [dot] com>
On Tue, Mar 17, 2009 at 11:15 AM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote:
Thanks for the link. I found this post by Martin Odersky:
"Scala has a return statement which allows one to exit prematurely from a loop
within a function. It does not have break or continue, and there are no plans to add them. The reason is that (1) break and continue add significantly to language complexity without giving that much gain. (2) break and continue are most often used in large methods; in Scala it's often preferable to split these up into smaller pieces. (3) break and continue complicate specification and implementation of closures (quite a bit so)."
Well, I won't argue with that, but let me just make a couple of points.
With regard to item 3, if break and continue cause problems with closures, why not just disallow them in closures rather than disallowing them completely? (I don't even recall what a closure is, so please disregard the previous sentence if it makes no sense.)
Here's a typical case where I use "continue": I'm reading an input data file and processing each line as I read it. If the line is empty, or if it is designated as a comment, I just want to skip it and move on to the next line. With "continue", I can handle that case with one simple line and not affect the rest of the code. Without "continue," I need to add a level of indentation to the logic for processing each line. That adds a level of complexity and makes the code just a bit harder to understand, which strikes me as a bad tradeoff.
You've hit on the very reason that continue is bad. If you find yourself looking for the continue keyword, chances are that you should rethink your implementation. In this case, you've described a filter:
val linesToIgnore = (s: String) => s.length == 0 || isComment(s)
So, if your input is a Seq[String] called lines, you can get the lines you want to deal with:
lines.remove(linesToIgnore)
Do you really propose that whenever he thinks he needs "continue", he should instead store his whole input in a Seq and then removing the unwanted elements? He was talking about sequentially parsing input files. Try parsing some files in the MBs this way.
Russ, just use scala.io.Source, then apply a filter to it, with the same condition you would put in your continue statement. For example:
for (x <- Source.fromFile("test.txt").getLines if x.length > 0) { println(x)
}
or equivalently:Source.fromFile("test.txt").getLines.filter(_.length > 0).foreach { println(_) }
(There are many possible syntactical variations of course)
Tue, 2009-03-17, 22:27
#4
Re: continue keyword
On Tue, Mar 17, 2009 at 1:44 PM, Jim Andreou <jim [dot] andreou [at] gmail [dot] com> wrote:
2009/3/17 David Pollak <feeder [dot] of [dot] the [dot] bears [at] gmail [dot] com>
On Tue, Mar 17, 2009 at 11:15 AM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote:
Thanks for the link. I found this post by Martin Odersky:
"Scala has a return statement which allows one to exit prematurely from a loop
within a function. It does not have break or continue, and there are no plans to add them. The reason is that (1) break and continue add significantly to language complexity without giving that much gain. (2) break and continue are most often used in large methods; in Scala it's often preferable to split these up into smaller pieces. (3) break and continue complicate specification and implementation of closures (quite a bit so)."
Well, I won't argue with that, but let me just make a couple of points.
With regard to item 3, if break and continue cause problems with closures, why not just disallow them in closures rather than disallowing them completely? (I don't even recall what a closure is, so please disregard the previous sentence if it makes no sense.)
Here's a typical case where I use "continue": I'm reading an input data file and processing each line as I read it. If the line is empty, or if it is designated as a comment, I just want to skip it and move on to the next line. With "continue", I can handle that case with one simple line and not affect the rest of the code. Without "continue," I need to add a level of indentation to the logic for processing each line. That adds a level of complexity and makes the code just a bit harder to understand, which strikes me as a bad tradeoff.
You've hit on the very reason that continue is bad. If you find yourself looking for the continue keyword, chances are that you should rethink your implementation. In this case, you've described a filter:
val linesToIgnore = (s: String) => s.length == 0 || isComment(s)
So, if your input is a Seq[String] called lines, you can get the lines you want to deal with:
lines.remove(linesToIgnore)
Do you really propose that whenever he thinks he needs "continue", he should instead store his whole input in a Seq and then removing the unwanted elements?
Seq is an interface, it does not define a particular structure for the underlying data. Stream is lazy and is a subclass of Seq, so you can do the following:
import java.io._
def inputToSeq(in: InputStream): Seq[String] = {
val br = new BufferedReader(new InputStreamReader(in))
def buildSeq: Stream[String] = br.readLine match {
case null => Stream.empty
case x => Stream.cons(x, buildSeq)
}
buildSeq
}
And you have a generic way to convert an InputStream into a Seq.
But at the end of the day, an Iterator (which is what Source.fromFile("test.txt").getLines returns) also has a filter method on it, so my original suggestion of filtering (remove is the inverse of filter) is the same suggestion that you made.
So, you have written the same code that I did. So what is it that you are trying to prove?
He was talking about sequentially parsing input files. Try parsing some files in the MBs this way.
Russ, just use scala.io.Source, then apply a filter to it, with the same condition you would put in your continue statement. For example:
for (x <- Source.fromFile("test.txt").getLines if x.length > 0) { println(x)
}
or equivalently:Source.fromFile("test.txt").getLines.filter(_.length > 0).foreach { println(_) }
(There are many possible syntactical variations of course)
--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp
Tue, 2009-03-17, 23:07
#5
Re: continue keyword
For what it's worth, Scala 2.8 will bring back break and continue, but
as library abstractions.
For instance,
import scala.util.control.Breaks._
breakable {
for (x <- elems) {
...
if (cond1) break
if (cond2) continue
...
}
}
In case you don't want to wait until 2.8, I append an implementation
of scala.util.control.Breaks that
does this. (and btw don't worry about efficiency -- control transfers
with pre-allocated exceptions are very fast from JVM 1.6)
Cheers
Tue, 2009-03-17, 23:17
#6
Re: continue keyword
Hi Martin,
probably I just don't get it, break leaves the breakable block, but continue starts it all over again, doesn't it?
So the semantic is different from Java, which would continue with the next element found in elems.
Don't get me wrong, I am personally fine without break and continue.
Kind regards,
Jan
2009/3/17 martin odersky <martin [dot] odersky [at] epfl [dot] ch>
probably I just don't get it, break leaves the breakable block, but continue starts it all over again, doesn't it?
So the semantic is different from Java, which would continue with the next element found in elems.
Don't get me wrong, I am personally fine without break and continue.
Kind regards,
Jan
2009/3/17 martin odersky <martin [dot] odersky [at] epfl [dot] ch>
For what it's worth, Scala 2.8 will bring back break and continue, but
as library abstractions.
For instance,
import scala.util.control.Breaks._
breakable {
for (x <- elems) {
...
if (cond1) break
if (cond2) continue
...
}
}
In case you don't want to wait until 2.8, I append an implementation
of scala.util.control.Breaks that
does this. (and btw don't worry about efficiency -- control transfers
with pre-allocated exceptions are very fast from JVM 1.6)
Cheers
Tue, 2009-03-17, 23:27
#7
Re: continue keyword
On Tue, Mar 17, 2009 at 11:15 PM, Jan Lohre wrote:
> Hi Martin,
>
> probably I just don't get it, break leaves the breakable block, but continue
> starts it all over again, doesn't it?
> So the semantic is different from Java, which would continue with the next
> element found in elems.
>
Yes, sorry, my mistake. It works for a while loop:
var i = 0
breakable {
while (i <= end) {
...
i += 1
if (cond) continue
...
}
}
but it would start a for loop all over again devery time it is
invoked. So, maybe we should just
provide break, that's more predictable.
Cheers
Tue, 2009-03-17, 23:47
#8
Re: continue keyword
O/H David Pollak έγραψε:
>
>
> On Tue, Mar 17, 2009 at 1:44 PM, Jim Andreou > wrote:
>
>
>
> 2009/3/17 David Pollak >
>
>
>
> On Tue, Mar 17, 2009 at 11:15 AM, Russ Paielli
> > wrote:
>
> Thanks for the link. I found this post by Martin Odersky:
>
> "Scala has a return statement which allows one to exit
> prematurely from a loop
> within a function. It does not have break or continue, and
> there are no plans to add them. The reason is that (1)
> break and continue add significantly to language
> complexity without giving that much gain. (2) break and
> continue are most often used in large methods; in Scala
> it's often preferable to split these up into smaller
> pieces. (3) break and continue complicate specification
> and implementation of closures (quite a bit so)."
>
> Well, I won't argue with that, but let me just make a
> couple of points.
>
> With regard to item 3, if break and continue cause
> problems with closures, why not just disallow them in
> closures rather than disallowing them completely? (I don't
> even recall what a closure is, so please disregard the
> previous sentence if it makes no sense.)
>
> Here's a typical case where I use "continue": I'm reading
> an input data file and processing each line as I read it.
> If the line is empty, or if it is designated as a comment,
> I just want to skip it and move on to the next line. With
> "continue", I can handle that case with one simple line
> and not affect the rest of the code. Without "continue," I
> need to add a level of indentation to the logic for
> processing each line. That adds a level of complexity and
> makes the code just a bit harder to understand, which
> strikes me as a bad tradeoff.
>
>
> You've hit on the very reason that continue is bad.� If you
> find yourself looking for the continue keyword, chances are
> that you should rethink your implementation.� In this case,
> you've described a filter:
>
> val linesToIgnore = (s: String) => s.length == 0 || isComment(s)
>
> So, if your input is a Seq[String] called lines, you can get
> the lines you want to deal with:
> lines.remove(linesToIgnore)
>
>
> Do you really propose that whenever he thinks he needs "continue",
> he should instead store his whole input in a Seq and then removing
> the unwanted elements?
>
>
>
> Seq is an interface, it does not define a particular structure for the
> underlying data.� Stream is lazy and is a subclass of Seq, so you can
> do the following:
>
> import java.io._
>
> def inputToSeq(in: InputStream): Seq[String] = {
> � val br = new BufferedReader(new InputStreamReader(in))
> � def buildSeq: Stream[String] = br.readLine match {
> ��� case null => Stream.empty
> ��� case x => Stream.cons(x, buildSeq)
> � }
> � buildSeq
> }
>
> And you have a generic way to convert an InputStream into a Seq.
>
> But at the end of the day, an Iterator (which is what
> Source.fromFile("test.txt").getLines returns) also has a filter method
> on it, so my original suggestion of filtering (remove is the inverse
> of filter) is the same suggestion that you made.
>
> So, you have written the same code that I did.� So what is it that you
> are trying to prove?
Your initial code showed a "remove" method called on a Seq, where a Seq
doesn't define it, neither Stream does. But MutableSeq does. So I hope
this clarifies the potential confusion, unless all readers interpreted
the "remove" on a "Seq" as meaning a filter to a stream. Well, at least
I didn't.
Now, please do post publicly your threats to me and my "company" (it's a
research institute actually). I'm sorry I ever disagreed with you. Other
people must also learn not to.
Wed, 2009-03-18, 00:27
#9
Re: continue keyword
On Tue, Mar 17, 2009 at 1:44 PM, Jim Andreou <jim [dot] andreou [at] gmail [dot] com> wrote:
Thanks. That's good information to know, but it's not quite exactly what I want in this case. It's equivalent to using continue only if continue is the first statement in the block. But I want to do something before I continue. For example, I want to keep a running count of the input line number for an error message in case something goes wrong.
Russ P.
Russ, just use scala.io.Source, then apply a filter to it, with the same condition you would put in your continue statement. For example:
for (x <- Source.fromFile("test.txt").getLines if x.length > 0) { println(x)
}
Thanks. That's good information to know, but it's not quite exactly what I want in this case. It's equivalent to using continue only if continue is the first statement in the block. But I want to do something before I continue. For example, I want to keep a running count of the input line number for an error message in case something goes wrong.
Russ P.
Wed, 2009-03-18, 00:37
#10
Re: continue keyword
Does that mean "continue" is out for 2.8?
Russ P.
On Tue, Mar 17, 2009 at 3:22 PM, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:
Russ P.
On Tue, Mar 17, 2009 at 3:22 PM, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:
On Tue, Mar 17, 2009 at 11:15 PM, Jan Lohre <jan [dot] lohre [at] googlemail [dot] com> wrote:
> Hi Martin,
>
> probably I just don't get it, break leaves the breakable block, but continue
> starts it all over again, doesn't it?
> So the semantic is different from Java, which would continue with the next
> element found in elems.
>
Yes, sorry, my mistake. It works for a while loop:
var i = 0
breakable {
while (i <= end) {
...
i += 1
if (cond) continue
...
}
}
but it would start a for loop all over again devery time it is
invoked. So, maybe we should just
provide break, that's more predictable.
Cheers
Wed, 2009-03-18, 00:57
#11
Re: continue keyword
Russ,
Assuming you have a Seq[String] or an Iterator[String] named lines, you can do something like:
var blankCnt = 0var commentCnt = 0
val usefulLines = lines.filter { case "" => blankCnt += 1 ; false case s if isComment(s) => commentCnt += 1; false case s => true}
This will filter out the blank lines and the comment lines, but count them.
Your filter function can have side effects.
On Tue, Mar 17, 2009 at 4:17 PM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote:
--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp
Assuming you have a Seq[String] or an Iterator[String] named lines, you can do something like:
var blankCnt = 0var commentCnt = 0
val usefulLines = lines.filter { case "" => blankCnt += 1 ; false case s if isComment(s) => commentCnt += 1; false case s => true}
This will filter out the blank lines and the comment lines, but count them.
Your filter function can have side effects.
On Tue, Mar 17, 2009 at 4:17 PM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote:
On Tue, Mar 17, 2009 at 1:44 PM, Jim Andreou <jim [dot] andreou [at] gmail [dot] com> wrote:
Russ, just use scala.io.Source, then apply a filter to it, with the same condition you would put in your continue statement. For example:
for (x <- Source.fromFile("test.txt").getLines if x.length > 0) { println(x)
}
Thanks. That's good information to know, but it's not quite exactly what I want in this case. It's equivalent to using continue only if continue is the first statement in the block. But I want to do something before I continue. For example, I want to keep a running count of the input line number for an error message in case something goes wrong.
Russ P.
--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp
Wed, 2009-03-18, 03:57
#12
Re: continue keyword
I played around with Martin's code, and I think I have a solution for the "continue" problem.
#!/bin/sh
exec scala "$0" "$@"
!#
object Breaks {
private class BreakException extends RuntimeException
private val breakException = new BreakException
def breakable(op: => Unit) {
try { op }
catch { case ex: BreakException => }
}
def break { throw breakException }
}
// Here is how you implement "break":
Breaks.breakable { for (i <- 0 to 8) {
println(i)
if (i > 4) Breaks.break
println(10+i)
}
}
println
println
// And here is how you implement "continue":
for (i <- 0 to 8) Breaks.breakable {
println(i)
if (i > 4) Breaks.break
println(10+i)
}
Now all we need is a way to get both "break" and "continue" in the same block.
Russ P.
On Tue, Mar 17, 2009 at 3:22 PM, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:
#!/bin/sh
exec scala "$0" "$@"
!#
object Breaks {
private class BreakException extends RuntimeException
private val breakException = new BreakException
def breakable(op: => Unit) {
try { op }
catch { case ex: BreakException => }
}
def break { throw breakException }
}
// Here is how you implement "break":
Breaks.breakable { for (i <- 0 to 8) {
println(i)
if (i > 4) Breaks.break
println(10+i)
}
}
println
println
// And here is how you implement "continue":
for (i <- 0 to 8) Breaks.breakable {
println(i)
if (i > 4) Breaks.break
println(10+i)
}
Now all we need is a way to get both "break" and "continue" in the same block.
Russ P.
On Tue, Mar 17, 2009 at 3:22 PM, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:
On Tue, Mar 17, 2009 at 11:15 PM, Jan Lohre <jan [dot] lohre [at] googlemail [dot] com> wrote:
> Hi Martin,
>
> probably I just don't get it, break leaves the breakable block, but continue
> starts it all over again, doesn't it?
> So the semantic is different from Java, which would continue with the next
> element found in elems.
>
Yes, sorry, my mistake. It works for a while loop:
var i = 0
breakable {
while (i <= end) {
...
i += 1
if (cond) continue
...
}
}
but it would start a for loop all over again devery time it is
invoked. So, maybe we should just
provide break, that's more predictable.
Cheers
Wed, 2009-03-18, 09:17
#13
Re: continue keyword
OK, I think I have the continue/break thing figured out. Here is the "Breaks" object:
object Breaks {
private class BreakException extends RuntimeException
private class ContinueException extends RuntimeException
private val breakException = new BreakException
private val continueException = new ContinueException
def breakable(op: => Unit) {
try { op }
catch { case ex: BreakException => }
}
def continuable(op: => Unit) {
try { op }
catch { case ex: ContinueException => }
}
def break { throw breakException }
def continue { throw continueException }
}
And here is an example of its usage:
#!/bin/sh
exec scala -classpath . "$0" "$@"
!#
import Breaks._
breakable { for (i <- 0 to 10) continuable {
if (i > 6) break
println(i)
if (i > 2) continue
println(1000+i)
}}
Now all I need is for some Scala wizard to abstract the "breakable/for/continuable" pattern into a simpler form, perhaps called "For" or some such thing. Anyone interested?
For a future version of Scala, maybe "for" can be renamed to something else, and the name "for" used for the continuable/breakable version.
Russ P.
--
http://RussP.us
object Breaks {
private class BreakException extends RuntimeException
private class ContinueException extends RuntimeException
private val breakException = new BreakException
private val continueException = new ContinueException
def breakable(op: => Unit) {
try { op }
catch { case ex: BreakException => }
}
def continuable(op: => Unit) {
try { op }
catch { case ex: ContinueException => }
}
def break { throw breakException }
def continue { throw continueException }
}
And here is an example of its usage:
#!/bin/sh
exec scala -classpath . "$0" "$@"
!#
import Breaks._
breakable { for (i <- 0 to 10) continuable {
if (i > 6) break
println(i)
if (i > 2) continue
println(1000+i)
}}
Now all I need is for some Scala wizard to abstract the "breakable/for/continuable" pattern into a simpler form, perhaps called "For" or some such thing. Anyone interested?
For a future version of Scala, maybe "for" can be renamed to something else, and the name "for" used for the continuable/breakable version.
Russ P.
--
http://RussP.us
Wed, 2009-03-18, 11:07
#14
Re: continue keyword
Hi Russ,
You are right, this could work the way you describe. But of course
you'll have noted that break and continue are exactly the same. We
need both to have break and continue in the same loop. It could also
be misused to break form two nested loops:
continuable {
for (i <- 0 until 10) {
breakable {
for (j <- 0 until 10) {
if (cond1) break
if (cond2) continue // breaks outer loop
...
}
}
}
A horrible mis-use I admit, but perfectly possible.
I wonder, how often do we need loops with both break and continue? So
far, in 4 years of Scala's existence neither break nor continue was
really missed, probably because people write tail-recursive functions
instead.
Then break becomes return and continue becomes tail-recursive call.
So a more modest extension would be to have just break. As you have
shown, one can model a continue by putting the breakable inside the
loop. I believe this makes it clearer what goes on.
Cheers
Wed, 2009-03-18, 11:17
#15
Re: continue keyword
Am Wednesday 18 March 2009 10:49:07 schrieb martin odersky:
>
> continuable {
> for (i <- 0 until 10) {
> breakable {
> for (j <- 0 until 10) {
> if (cond1) break
> if (cond2) continue // breaks outer loop
> ...
> }
> }
> }
>
> A horrible mis-use I admit, but perfectly possible.
now you (nearly) arrived at the labled versions of break / continue of
java :-)
Michael
Wed, 2009-03-18, 11:37
#16
Re: continue keyword
2009/3/18 Michael :
> Am Wednesday 18 March 2009 10:49:07 schrieb martin odersky:
>>
>> continuable {
>> for (i <- 0 until 10) {
>> breakable {
>> for (j <- 0 until 10) {
>> if (cond1) break
>> if (cond2) continue // breaks outer loop
>> ...
>> }
>> }
>> }
>>
>> A horrible mis-use I admit, but perfectly possible.
>
>
> now you (nearly) arrived at the labled versions of break / continue of
> java :-)
It's actually almost totally trivial to support labels in
break/continue as a library. The question is: Is it worth doing?
Wed, 2009-03-18, 12:17
#17
Re: continue keyword
On Wed, Mar 18, 2009 at 11:28 AM, David MacIver wrote:
> 2009/3/18 Michael :
>> Am Wednesday 18 March 2009 10:49:07 schrieb martin odersky:
>>>
>>> continuable {
>>> for (i <- 0 until 10) {
>>> breakable {
>>> for (j <- 0 until 10) {
>>> if (cond1) break
>>> if (cond2) continue // breaks outer loop
>>> ...
>>> }
>>> }
>>> }
>>>
>>> A horrible mis-use I admit, but perfectly possible.
>>
>>
>> now you (nearly) arrived at the labled versions of break / continue of
>> java :-)
>
> It's actually almost totally trivial to support labels in
> break/continue as a library.
True. For instance like this:
object LabelledBreak {
class Label extends Exception {
def dup = clone.asInstanceOf[Label]
}
private val protoLabel = new Label
def label(op: Label => Unit): Unit = {
val lbl = protoLabel.dup
try {
op(lbl)
} catch {
case ex: Label =>
if (ex != lbl) throw ex
}
}
def break(lbl: Label) = throw lbl
}
Usage:
import LabelledBreak._
label { L =>
...
if (cond) break(L)
...
}
> The question is: Is it worth doing?
I don't know. What do people think?
Cheers
Wed, 2009-03-18, 12:27
#18
Re: continue keyword
I'd rather not see break and continue myself. I think they tend to
violate expression oriented programming. Also, part of our *java*
coding standard recommends avoiding them.
On Mar 18, 2009, at 7:09 AM, martin odersky
wrote:
> On Wed, Mar 18, 2009 at 11:28 AM, David MacIver > wrote:
>> 2009/3/18 Michael :
>>> Am Wednesday 18 March 2009 10:49:07 schrieb martin odersky:
>>>>
>>>> continuable {
>>>> for (i <- 0 until 10) {
>>>> breakable {
>>>> for (j <- 0 until 10) {
>>>> if (cond1) break
>>>> if (cond2) continue // breaks outer loop
>>>> ...
>>>> }
>>>> }
>>>> }
>>>>
>>>> A horrible mis-use I admit, but perfectly possible.
>>>
>>>
>>> now you (nearly) arrived at the labled versions of break /
>>> continue of
>>> java :-)
>>
>> It's actually almost totally trivial to support labels in
>> break/continue as a library.
>
> True. For instance like this:
>
> object LabelledBreak {
>
> class Label extends Exception {
> def dup = clone.asInstanceOf[Label]
> }
>
> private val protoLabel = new Label
>
> def label(op: Label => Unit): Unit = {
> val lbl = protoLabel.dup
> try {
> op(lbl)
> } catch {
> case ex: Label =>
> if (ex != lbl) throw ex
> }
> }
> def break(lbl: Label) = throw lbl
> }
>
> Usage:
>
> import LabelledBreak._
>
> label { L =>
> ...
> if (cond) break(L)
> ...
> }
>
>> The question is: Is it worth doing?
>
> I don't know. What do people think?
>
> Cheers
>
Wed, 2009-03-18, 12:57
#19
Re: continue keyword
I'm against the use of break/continue
As stated earlier in this thread, when you find yourself needing them, then your logic is messed up. Take a step back and rethink the implementation.
On Wed, Mar 18, 2009 at 12:26 PM, Josh Suereth <joshua [dot] suereth [at] gmail [dot] com> wrote:
As stated earlier in this thread, when you find yourself needing them, then your logic is messed up. Take a step back and rethink the implementation.
On Wed, Mar 18, 2009 at 12:26 PM, Josh Suereth <joshua [dot] suereth [at] gmail [dot] com> wrote:
I'd rather not see break and continue myself. I think they tend to violate expression oriented programming. Also, part of our *java* coding standard recommends avoiding them.
On Mar 18, 2009, at 7:09 AM, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:
On Wed, Mar 18, 2009 at 11:28 AM, David MacIver <david [dot] maciver [at] gmail [dot] com> wrote:
2009/3/18 Michael <micha-1 [at] fantasymail [dot] de>:
Am Wednesday 18 March 2009 10:49:07 schrieb martin odersky:
continuable {
for (i <- 0 until 10) {
breakable {
for (j <- 0 until 10) {
if (cond1) break
if (cond2) continue // breaks outer loop
...
}
}
}
A horrible mis-use I admit, but perfectly possible.
now you (nearly) arrived at the labled versions of break / continue of
java :-)
It's actually almost totally trivial to support labels in
break/continue as a library.
True. For instance like this:
object LabelledBreak {
class Label extends Exception {
def dup = clone.asInstanceOf[Label]
}
private val protoLabel = new Label
def label(op: Label => Unit): Unit = {
val lbl = protoLabel.dup
try {
op(lbl)
} catch {
case ex: Label =>
if (ex != lbl) throw ex
}
}
def break(lbl: Label) = throw lbl
}
Usage:
import LabelledBreak._
label { L =>
...
if (cond) break(L)
...
}
The question is: Is it worth doing?
I don't know. What do people think?
Cheers
Wed, 2009-03-18, 13:07
#20
Re: continue keyword
They are statement-orientated, sure, but some code is, for better or
worse. Does your Java coding standard also disallow multiple returns
per method?
2009/3/18 Josh Suereth :
> I'd rather not see break and continue myself. I think they tend to violate
> expression oriented programming. Also, part of our *java* coding standard
> recommends avoiding them.
>
>
>
> On Mar 18, 2009, at 7:09 AM, martin odersky wrote:
>
>> On Wed, Mar 18, 2009 at 11:28 AM, David MacIver
>> wrote:
>>>
>>> 2009/3/18 Michael :
>>>>
>>>> Am Wednesday 18 March 2009 10:49:07 schrieb martin odersky:
>>>>>
>>>>> continuable {
>>>>> for (i <- 0 until 10) {
>>>>> breakable {
>>>>> for (j <- 0 until 10) {
>>>>> if (cond1) break
>>>>> if (cond2) continue // breaks outer loop
>>>>> ...
>>>>> }
>>>>> }
>>>>> }
>>>>>
>>>>> A horrible mis-use I admit, but perfectly possible.
>>>>
>>>>
>>>> now you (nearly) arrived at the labled versions of break / continue of
>>>> java :-)
>>>
>>> It's actually almost totally trivial to support labels in
>>> break/continue as a library.
>>
>> True. For instance like this:
>>
>> object LabelledBreak {
>>
>> class Label extends Exception {
>> def dup = clone.asInstanceOf[Label]
>> }
>>
>> private val protoLabel = new Label
>>
>> def label(op: Label => Unit): Unit = {
>> val lbl = protoLabel.dup
>> try {
>> op(lbl)
>> } catch {
>> case ex: Label =>
>> if (ex != lbl) throw ex
>> }
>> }
>> def break(lbl: Label) = throw lbl
>> }
>>
>> Usage:
>>
>> import LabelledBreak._
>>
>> label { L =>
>> ...
>> if (cond) break(L)
>> ...
>> }
>>
>>> The question is: Is it worth doing?
>>
>> I don't know. What do people think?
>>
>> Cheers
>>
Wed, 2009-03-18, 13:27
#21
Re: continue keyword
+1
On Wed, Mar 18, 2009 at 6:26 AM, Josh Suereth wrote:
> I'd rather not see break and continue myself. I think they tend to violate
> expression oriented programming. Also, part of our *java* coding standard
> recommends avoiding them.
In the early 70s--the early days of "structured programming"--there
were lots of tricks (loop wrapped around a "where-am-I" switch, etc.)
for simulating GOTOs.
In the late 80s and early 90s--the early years of mainstream
OOP--there were lots of huge classes full of static methods that let
folks pretend they were still writing C.
If Scala needs to simulate control-flow devices as part of the
transitional scaffolding, so be it. Personally speaking, I have
benefited more from working to adopt a new thought process than from
trying to force-fit an old approach onto a new language.
I've really appreciated the posts that take the approach: "If this is
what you're really trying to accomplish, then here's a new idiom that
does that well."
-jn-
Wed, 2009-03-18, 14:17
#22
Re: continue keyword
Yes, but I do violate that one
Sent from my iPhone
On Mar 18, 2009, at 7:34 AM, Ricky Clarkson
wrote:
> They are statement-orientated, sure, but some code is, for better or
> worse. Does your Java coding standard also disallow multiple returns
> per method?
>
> 2009/3/18 Josh Suereth :
>> I'd rather not see break and continue myself. I think they tend to
>> violate
>> expression oriented programming. Also, part of our *java* coding
>> standard
>> recommends avoiding them.
>>
>>
>>
>> On Mar 18, 2009, at 7:09 AM, martin odersky
>> wrote:
>>
>>> On Wed, Mar 18, 2009 at 11:28 AM, David MacIver >> >
>>> wrote:
>>>>
>>>> 2009/3/18 Michael :
>>>>>
>>>>> Am Wednesday 18 March 2009 10:49:07 schrieb martin odersky:
>>>>>>
>>>>>> continuable {
>>>>>> for (i <- 0 until 10) {
>>>>>> breakable {
>>>>>> for (j <- 0 until 10) {
>>>>>> if (cond1) break
>>>>>> if (cond2) continue // breaks outer loop
>>>>>> ...
>>>>>> }
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> A horrible mis-use I admit, but perfectly possible.
>>>>>
>>>>>
>>>>> now you (nearly) arrived at the labled versions of break /
>>>>> continue of
>>>>> java :-)
>>>>
>>>> It's actually almost totally trivial to support labels in
>>>> break/continue as a library.
>>>
>>> True. For instance like this:
>>>
>>> object LabelledBreak {
>>>
>>> class Label extends Exception {
>>> def dup = clone.asInstanceOf[Label]
>>> }
>>>
>>> private val protoLabel = new Label
>>>
>>> def label(op: Label => Unit): Unit = {
>>> val lbl = protoLabel.dup
>>> try {
>>> op(lbl)
>>> } catch {
>>> case ex: Label =>
>>> if (ex != lbl) throw ex
>>> }
>>> }
>>> def break(lbl: Label) = throw lbl
>>> }
>>>
>>> Usage:
>>>
>>> import LabelledBreak._
>>>
>>> label { L =>
>>> ...
>>> if (cond) break(L)
>>> ...
>>> }
>>>
>>>> The question is: Is it worth doing?
>>>
>>> I don't know. What do people think?
>>>
>>> Cheers
>>>
>>> -- Martin
>>
Wed, 2009-03-18, 14:27
#23
Re: continue keyword
2009/3/18 Josh Suereth :
> I'd rather not see break and continue myself. I think they tend to violate
> expression oriented programming.
No they don't. They're perfectly compatible with expression oriented
programming: They're expressions of type Nothing.
> Also, part of our *java* coding standard
> recommends avoiding them.
Java coding standards are invariably bollocks even in Java, so I don't
consider that a compelling argument. :-)
Wed, 2009-03-18, 14:37
#24
Re: continue keyword
Sent from my iPhone
On Mar 18, 2009, at 9:06 AM, David MacIver
wrote:
> 2009/3/18 Josh Suereth :
>> I'd rather not see break and continue myself. I think they tend to
>> violate
>> expression oriented programming.
>
> No they don't. They're perfectly compatible with expression oriented
> programming: They're expressions of type Nothing.
>
>> Also, part of our *java* coding standard
>> recommends avoiding them.
>
> Java coding standards are invariably bollocks even in Java, so I don't
> consider that a compelling argument. :-)
How about this: I'd rather have the smart people spending time adding
other niceties to the language. I think people are used to avoiding
break/continue so their absence should only cause temporary discomfort.
Wed, 2009-03-18, 14:47
#25
Re: continue keyword
2009/3/18 Josh Suereth :
>> Java coding standards are invariably bollocks even in Java, so I don't
>> consider that a compelling argument. :-)
>
> How about this: I'd rather have the smart people spending time adding other
> niceties to the language. I think people are used to avoiding
> break/continue so their absence should only cause temporary discomfort.
Note that no one (sensible) is suggesting adding break and continue as
language features. The discussion is over adding them as a library.
And given that the collections library is undergoing redesign anyway,
it's useful to think about what functionality we can add to enrich its
usage.
Adding break and continue, particularly in a way that plays nicely
with the language and causes all the higher order functions on
Iterable inherit sensible uses of it, adds a bunch of neat tricks you
can do and makes certain things noticably easier to write. It's also
very low implementation cost (we've spent more time arguing about it
than it would take to implement. :-) ).
Wed, 2009-03-18, 15:27
#26
Re: continue keyword
In that case, go for it!
I'd also love to see the lolz library also be included in the new collections ;)
On Wed, Mar 18, 2009 at 9:28 AM, David MacIver <david [dot] maciver [at] gmail [dot] com> wrote:
I'd also love to see the lolz library also be included in the new collections ;)
On Wed, Mar 18, 2009 at 9:28 AM, David MacIver <david [dot] maciver [at] gmail [dot] com> wrote:
2009/3/18 Josh Suereth <joshua [dot] suereth [at] gmail [dot] com>:
>> Java coding standards are invariably bollocks even in Java, so I don't
>> consider that a compelling argument. :-)
>
> How about this: I'd rather have the smart people spending time adding other
> niceties to the language. I think people are used to avoiding
> break/continue so their absence should only cause temporary discomfort.
Note that no one (sensible) is suggesting adding break and continue as
language features. The discussion is over adding them as a library.
And given that the collections library is undergoing redesign anyway,
it's useful to think about what functionality we can add to enrich its
usage.
Adding break and continue, particularly in a way that plays nicely
with the language and causes all the higher order functions on
Iterable inherit sensible uses of it, adds a bunch of neat tricks you
can do and makes certain things noticably easier to write. It's also
very low implementation cost (we've spent more time arguing about it
than it would take to implement. :-) ).
Wed, 2009-03-18, 15:58
#27
Re: continue keyword
It seems to me that this type of implementation may already be a good compromise. It means that loops that contain break and continue must be marked, and look slightly ugly. That will encourage people to use other techniques that are more FP correct. Also if I use break or continue I make a point of writing a comment saying so ("while(true) // Contains break") and this would basically enforce that convention.
It would make sense to me to add continuable and breakable (or something that is both all in one) to the standard library, but making "for" include them by default seems like a bad idea.
That being said, I'm a newb so feel free to ignore my ramblings. ;-)
-Arthur
On Wed, Mar 18, 2009 at 3:52 AM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote:
It would make sense to me to add continuable and breakable (or something that is both all in one) to the standard library, but making "for" include them by default seems like a bad idea.
That being said, I'm a newb so feel free to ignore my ramblings. ;-)
-Arthur
On Wed, Mar 18, 2009 at 3:52 AM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote:
OK, I think I have the continue/break thing figured out. Here is the "Breaks" object:
object Breaks {
private class BreakException extends RuntimeException
private class ContinueException extends RuntimeException
private val breakException = new BreakException
private val continueException = new ContinueException
def breakable(op: => Unit) {
try { op }
catch { case ex: BreakException => }
}
def continuable(op: => Unit) {
try { op }
catch { case ex: ContinueException => }
}
def break { throw breakException }
def continue { throw continueException }
}
And here is an example of its usage:
#!/bin/sh
exec scala -classpath . "$0" "$@"
!#
import Breaks._
breakable { for (i <- 0 to 10) continuable {
if (i > 6) break
println(i)
if (i > 2) continue
println(1000+i)
}}
Now all I need is for some Scala wizard to abstract the "breakable/for/continuable" pattern into a simpler form, perhaps called "For" or some such thing. Anyone interested?
For a future version of Scala, maybe "for" can be renamed to something else, and the name "for" used for the continuable/breakable version.
Russ P.
Wed, 2009-03-18, 16:07
#28
Re: continue keyword
2009/3/18 Arthur Peters :
> It seems to me that this type of implementation may already be a good
> compromise. It means that loops that contain break and continue must be
> marked, and look slightly ugly. That will encourage people to use other
> techniques that are more FP correct. Also if I use break or continue I make
> a point of writing a comment saying so ("while(true) // Contains break") and
> this would basically enforce that convention.
>
> It would make sense to me to add continuable and breakable (or something
> that is both all in one) to the standard library, but making "for" include
> them by default seems like a bad idea.
It's certainly possible to add it as a library without integrating it
into the collections, but that would be sad. You get neat stuff for
free if you do implement it in the standard foreach. :-)
Wed, 2009-03-18, 18:27
#29
Re: continue keyword
Would it be too rude to say that 'continue' turns a functional language into dysfunctional?
2009/3/17 Russ Paielli <russ [dot] paielli [at] gmail [dot] com>
--
Thanks,
-Vlad
2009/3/17 Russ Paielli <russ [dot] paielli [at] gmail [dot] com>
Thanks for the link. I found this post by Martin Odersky:
"Scala has a return statement which allows one to exit prematurely from a loop
within a function. It does not have break or continue, and there are no plans to add them. The reason is that (1) break and continue add significantly to language complexity without giving that much gain. (2) break and continue are most often used in large methods; in Scala it's often preferable to split these up into smaller pieces. (3) break and continue complicate specification and implementation of closures (quite a bit so)."
Well, I won't argue with that, but let me just make a couple of points.
With regard to item 3, if break and continue cause problems with closures, why not just disallow them in closures rather than disallowing them completely? (I don't even recall what a closure is, so please disregard the previous sentence if it makes no sense.)
Here's a typical case where I use "continue": I'm reading an input data file and processing each line as I read it. If the line is empty, or if it is designated as a comment, I just want to skip it and move on to the next line. With "continue", I can handle that case with one simple line and not affect the rest of the code. Without "continue," I need to add a level of indentation to the logic for processing each line. That adds a level of complexity and makes the code just a bit harder to understand, which strikes me as a bad tradeoff.
I will concede that "continue" can sometimes complicate debugging a bit, but I don't think it is any worse than an early return, which is allowed in Scala.
Russ P.
--
Thanks,
-Vlad
Wed, 2009-03-18, 18:57
#30
Re: continue keyword
2009/3/18 Vlad Patryshev :
> Would it be too rude to say that 'continue' turns a functional language into
> dysfunctional?
Would it be rude to say that making clever puns does not constitute a
valid substitute for having a point?
Wed, 2009-03-18, 19:57
#31
Re: continue keyword
Oh, okay.
See, if we have "continue" in a closure, we sure mean that we know exactly how the closure should be used. That it in a sense controls the way the quantifier works, right?
On the other hand, there are very convenient if-then-else constructs that work independently of the context, right?
The only way "continue" (or "break") is considered useful if we treat our code as a sequence of actions followed by other actions. So the main question while writing the code is something like "okay, what next?". This is a pretty ancient paradigm, and, in my view, it is not the way to express or solve problems.
2009/3/18 David MacIver <david [dot] maciver [at] gmail [dot] com>
--
Thanks,
-Vlad
See, if we have "continue" in a closure, we sure mean that we know exactly how the closure should be used. That it in a sense controls the way the quantifier works, right?
On the other hand, there are very convenient if-then-else constructs that work independently of the context, right?
The only way "continue" (or "break") is considered useful if we treat our code as a sequence of actions followed by other actions. So the main question while writing the code is something like "okay, what next?". This is a pretty ancient paradigm, and, in my view, it is not the way to express or solve problems.
2009/3/18 David MacIver <david [dot] maciver [at] gmail [dot] com>
2009/3/18 Vlad Patryshev <vpatryshev [at] gmail [dot] com>:
> Would it be too rude to say that 'continue' turns a functional language into
> dysfunctional?
Would it be rude to say that making clever puns does not constitute a
valid substitute for having a point?
--
Thanks,
-Vlad
Wed, 2009-03-18, 20:07
#32
Re: continue keyword
2009/3/18 Vlad Patryshev :
> Oh, okay.
> See, if we have "continue" in a closure, we sure mean that we know exactly
> how the closure should be used. That it in a sense controls the way the
> quantifier works, right?
> On the other hand, there are very convenient if-then-else constructs that
> work independently of the context, right?
If by "work independently of the context" you mean "do a strict subset
of the things that using break and continue allows us to do", yes.
> The only way "continue" (or "break") is considered useful if we treat our
> code as a sequence of actions followed by other actions. So the main
Scala is multiparadigm. In particular, Scala is an imperative
language. It supports functional programming as well, and it blends
the two nicely. So the fact that a construct is only useful when we
"treat our code as a sequence of actions followed by other actions" is
not an argument against its use in Scala.
> question while writing the code is something like "okay, what next?". This
> is a pretty ancient paradigm, and, in my view, it is not the way to express
> or solve problems.
I'm sorry, but I don't consider your religious views to be valid
criteria for library design.
Wed, 2009-03-18, 20:07
#33
Re: continue keyword
How about we add it as a library and add a new "brokenForeach" method to
collections that automatically includes Breakable and Continuable ;)
Derek
Wed, 2009-03-18, 20:57
#34
Re: continue keyword
On Wed, Mar 18, 2009 at 11:58 AM, David MacIver <david [dot] maciver [at] gmail [dot] com> wrote:
I agree. I don't claim to be an expert on this matter, but it seems to me that the three major programming "paradigms" are procedural, functional, and object oriented. It also seems to me that they are not mutually exclusive and can be combined in all sorts of ways.
Because a language supports functional programming, that is no reason it should not fully support procedural programming as well. Some problems are best solved by a procedural approach, and that approach should not be looked down on as too "unsophisticated" for advanced programmers.
One of the major problems with Java, as far as I am concerned, is that it tried to force-fit everything into the object-oriented approach whether it makes sense or not for a particular application. Trying to force-fit everything into a functional or object-oriented approach would be almost as bad.
As for "continue" and "break," I have found them to be useful and convenient in Python. As I explained before, they allow me to handle special cases in a single line without changing the structure of the remainder of the block (i.e., without adding another set of braces and another level of indentation). I think that makes my code simpler and easier to read.
Some people here have said that I can use a filter instead of "continue." That is true, but I think "continue" is often simpler and easier to read. The filter approach makes sense to me only if the "continue" statement is the first line of the block, but often it is not.
Russ P.
--
http://RussP.us
Scala is multiparadigm. In particular, Scala is an imperative
language. It supports functional programming as well, and it blends
the two nicely. So the fact that a construct is only useful when we
"treat our code as a sequence of actions followed by other actions" is
not an argument against its use in Scala.
I agree. I don't claim to be an expert on this matter, but it seems to me that the three major programming "paradigms" are procedural, functional, and object oriented. It also seems to me that they are not mutually exclusive and can be combined in all sorts of ways.
Because a language supports functional programming, that is no reason it should not fully support procedural programming as well. Some problems are best solved by a procedural approach, and that approach should not be looked down on as too "unsophisticated" for advanced programmers.
One of the major problems with Java, as far as I am concerned, is that it tried to force-fit everything into the object-oriented approach whether it makes sense or not for a particular application. Trying to force-fit everything into a functional or object-oriented approach would be almost as bad.
As for "continue" and "break," I have found them to be useful and convenient in Python. As I explained before, they allow me to handle special cases in a single line without changing the structure of the remainder of the block (i.e., without adding another set of braces and another level of indentation). I think that makes my code simpler and easier to read.
Some people here have said that I can use a filter instead of "continue." That is true, but I think "continue" is often simpler and easier to read. The filter approach makes sense to me only if the "continue" statement is the first line of the block, but often it is not.
Russ P.
--
http://RussP.us
Wed, 2009-03-18, 21:47
#35
Re: continue keyword
On Wednesday March 18 2009, Russ Paielli wrote:
> On Wed, Mar 18, 2009 at 11:58 AM, David MacIver wrote:
> > ...
>
> I agree. I don't claim to be an expert on this matter, but it seems
> to me that the three major programming "paradigms" are procedural,
> functional, and object oriented. It also seems to me that they are
> not mutually exclusive and can be combined in all sorts of ways.
Don't forget logic programming.
> Because a language supports functional programming, that is no reason
> it should not fully support procedural programming as well. Some
> problems are best solved by a procedural approach, and that approach
> should not be looked down on as too "unsophisticated" for advanced
> programmers.
Generally speaking, there's a design tension between the different
conceptual models of computer programming. It's not going to be
possible to be all things to all paradigms, as it were. I think we can
trust that the designers have done their best to balance the concerns
of the different programming modes, but the point is to favor the
functional over the side-effected programming when push comes to shove.
I really don't believe this is about any value judgements over the
degree of sophistication of once approach vs. another. It is, in fact,
pragmattic, when you look at the consequences of programming with
liberal use of side-effected representations and algorithms.
Concurrency and overall reliability are both enhanced when mutable
state is reduced.
> One of the major problems with Java, as far as I am concerned, is
> that it tried to force-fit everything into the object-oriented
> approach whether it makes sense or not for a particular application.
> Trying to force-fit everything into a functional or object-oriented
> approach would be almost as bad.
If you want to see what forcing functional programming looks like, my
understanding is that Haskell is much purer in this regard. But I've
never used it or studied it, so take that with a grain of salt.
> ...
>
> Some people here have said that I can use a filter instead of
> "continue." That is true, but I think "continue" is often simpler and
> easier to read. The filter approach makes sense to me only if the
> "continue" statement is the first line of the block, but often it is
> not.
What is simpler or easier to read tends to be pretty subjective, so if
you do pursue Scala programming, I'd expect your outlook to change over
time.
> Russ P.
Randall Schulz
Wed, 2009-03-18, 22:37
#36
Re: continue keyword
I have written a response here:
http://www.drmaciver.com/2009/03/left-folds-with-early-termination/
Wed, 2009-03-18, 23:17
#37
Re: continue keyword
On Wed, Mar 18, 2009 at 2:34 PM, David MacIver <david [dot] maciver [at] gmail [dot] com> wrote:
Thanks for sharing. I agree it would be useful (at times) to have this kind of early-termination facility in the upcoming collections API.
alex
I have written a response here:
http://www.drmaciver.com/2009/03/left-folds-with-early-termination/
Thanks for sharing. I agree it would be useful (at times) to have this kind of early-termination facility in the upcoming collections API.
alex
Wed, 2009-03-18, 23:47
#38
Re: continue keyword
On 3/18/09, David MacIver wrote:
> I have written a response here:
>
> http://www.drmaciver.com/2009/03/left-folds-with-early-termination/
>
To me it seems overengineering.
You just use an elaborate mechanism to write something that is
perfectly well written as a simple combination of takeWhile and
foldLeft : functional, modular and does not need throwing around
exceptions.
Wed, 2009-03-18, 23:47
#39
Re: continue keyword
2009/3/18 Christian Szegedy :
> On 3/18/09, David MacIver wrote:
>> I have written a response here:
>>
>> http://www.drmaciver.com/2009/03/left-folds-with-early-termination/
>>
> To me it seems overengineering.
>
> You just use an elaborate mechanism to write something that is
> perfectly well written as a simple combination of takeWhile and
> foldLeft : functional, modular and does not need throwing around
> exceptions.
Please write the following example using takeWhile:
myInts.foldLeft(0)((s, t) => if (s > 1000) break; else s * t)
Thu, 2009-03-19, 00:07
#40
Re: continue keyword
2009/3/18 David MacIver :
> 2009/3/18 Christian Szegedy :
>> On 3/18/09, David MacIver wrote:
>>> I have written a response here:
>>>
>>> http://www.drmaciver.com/2009/03/left-folds-with-early-termination/
>>>
>> To me it seems overengineering.
>>
>> You just use an elaborate mechanism to write something that is
>> perfectly well written as a simple combination of takeWhile and
>> foldLeft : functional, modular and does not need throwing around
>> exceptions.
>
> Please write the following example using takeWhile:
>
> myInts.foldLeft(0)((s, t) => if (s > 1000) break; else s * t)
Sorry.
myInts.foldLeft(1)((s, t) => if (s > 1000) break else s * t)
Multiplying by zero is not very useful. :-)
Thu, 2009-03-19, 01:57
#41
Re: continue keyword
> Because a language supports functional programming, that is no reason it
> should not fully support procedural programming as well.
A useful tool languages can give in functional programming is a
guarantee of referential transparency. This is at odds with
procedural programming, or so it at first appears. Haskell has
guaranteed referential transparency (barring unsafeFireTheMissiles
etc.), but can still do useful stuff because it has a separate
concept, actions (see the IO monad). Haskell does its best to
partition functional and imperative code. Scala's approach of mixing
functional and imperative code makes it not as good for functional
programming. So in one sense a language that supports functional
programming cannot fully support procedural programming as well, at
least without some kind of divider (IO, World -> World functions, or
just a different sublanguage), as "supports functional programming"
means "help the programmer in preventing procedural programming".
All that said, Scala's approach hurts the head less, and the mix has
its own merits.
Some problems are
> best solved by a procedural approach, and that approach should not be looked
> down on as too "unsophisticated" for advanced programmers.
>
> One of the major problems with Java, as far as I am concerned, is that it
> tried to force-fit everything into the object-oriented approach whether it
> makes sense or not for a particular application. Trying to force-fit
> everything into a functional or object-oriented approach would be almost as
> bad.
>
> As for "continue" and "break," I have found them to be useful and convenient
> in Python. As I explained before, they allow me to handle special cases in a
> single line without changing the structure of the remainder of the block
> (i.e., without adding another set of braces and another level of
> indentation). I think that makes my code simpler and easier to read.
>
> Some people here have said that I can use a filter instead of "continue."
> That is true, but I think "continue" is often simpler and easier to read.
> The filter approach makes sense to me only if the "continue" statement is
> the first line of the block, but often it is not.
>
> Russ P.
>
> --
> http://RussP.us
>
Thu, 2009-03-19, 02:07
#42
Re: continue keyword
I see your point.Indeed, this is a good example.
However, I would rather have general method (let us call it foldAccum)
of Stream[T] that generates a new stream of left folded elements for
the first n element of the input stream (currently not in the scala stdlib).
Then I could (still lazily) combine it with filter and first, like:
myints.foldAccum(1)( _ * _).filter( _ < 1000).first
However, I can agree with you that for someone coming from Java this would
look less readable and may become a bit unwieldly if things get more
complicated.
On 3/18/09, David MacIver wrote:
> 2009/3/18 David MacIver :
>
> > 2009/3/18 Christian Szegedy :
> >> On 3/18/09, David MacIver wrote:
> >>> I have written a response here:
> >>>
> >>> http://www.drmaciver.com/2009/03/left-folds-with-early-termination/
> >>>
> >> To me it seems overengineering.
> >>
> >> You just use an elaborate mechanism to write something that is
> >> perfectly well written as a simple combination of takeWhile and
> >> foldLeft : functional, modular and does not need throwing around
> >> exceptions.
> >
> > Please write the following example using takeWhile:
> >
> > myInts.foldLeft(0)((s, t) => if (s > 1000) break; else s * t)
>
>
> Sorry.
>
> myInts.foldLeft(1)((s, t) => if (s > 1000) break else s * t)
>
> Multiplying by zero is not very useful. :-)
>
Thu, 2009-03-19, 02:17
#43
Re: continue keyword
On Wed, Mar 18, 2009 at 2:49 AM, martin odersky <martin [dot] odersky [at] epfl [dot] ch> wrote:
Yes, using break and continue in the same loop is probably not very common, but let me give you an example where I have done that.
I routinely process air traffic data files that consist of recorded real-time inputs to a particular air traffic system. Each line of text is a data record with a time tag and other data of various types: radar tracks, route assignments, altitude assignments, etc.
Sometimes I have very large data files with hundreds of flights for many hours. Often I want to process only a particular time window with specific start and end times.
My loop reads each data line, parses it, and processes it. If it's a blank line or a comment, I use "continue" to skip it. Otherwise, I need to determine the record type and the time tag. If the time tag preceeds the specified start time, I may skip it or process it, depending on the record type. To skip it, I use "continue." If the time tag is past the end time, I use "break" to terminate the loop.
Now, I'm sure all that can be done without "continue" or "break," but I venture to say that the resulting code would be significantly more difficult both to write and to read.
Yes, if you only need "continue" and not "break" for a particular loop, but I'd just be careful not to use the word "break" to mean "continue." That could be confusing.
Russ P.
--
http://RussP.us
I wonder, how often do we need loops with both break and continue? So
far, in 4 years of Scala's existence neither break nor continue was
really missed, probably because people write tail-recursive functions
instead.
Yes, using break and continue in the same loop is probably not very common, but let me give you an example where I have done that.
I routinely process air traffic data files that consist of recorded real-time inputs to a particular air traffic system. Each line of text is a data record with a time tag and other data of various types: radar tracks, route assignments, altitude assignments, etc.
Sometimes I have very large data files with hundreds of flights for many hours. Often I want to process only a particular time window with specific start and end times.
My loop reads each data line, parses it, and processes it. If it's a blank line or a comment, I use "continue" to skip it. Otherwise, I need to determine the record type and the time tag. If the time tag preceeds the specified start time, I may skip it or process it, depending on the record type. To skip it, I use "continue." If the time tag is past the end time, I use "break" to terminate the loop.
Now, I'm sure all that can be done without "continue" or "break," but I venture to say that the resulting code would be significantly more difficult both to write and to read.
So a more modest extension would be to have just break. As you have
shown, one can model a continue by putting the breakable inside the
loop. I believe this makes it clearer what goes on.
Yes, if you only need "continue" and not "break" for a particular loop, but I'd just be careful not to use the word "break" to mean "continue." That could be confusing.
Russ P.
--
http://RussP.us
Thu, 2009-03-19, 02:57
#44
Re: continue keyword
data.takeWhile(_.time < endTime).filter(_.time > startTime).map(line
=> println("Found "+line.recordType+" at "+line.time))
Add projection to taste.
> My loop reads each data line, parses it, and processes it. If it's a blank
> line or a comment, I use "continue" to skip it. Otherwise, I need to
> determine the record type and the time tag. If the time tag preceeds the
> specified start time, I may skip it or process it, depending on the record
> type. To skip it, I use "continue." If the time tag is past the end time, I
> use "break" to terminate the loop.
>
> Now, I'm sure all that can be done without "continue" or "break," but I
> venture to say that the resulting code would be significantly more difficult
> both to write and to read.
>
>
>>
>> So a more modest extension would be to have just break. As you have
>> shown, one can model a continue by putting the breakable inside the
>> loop. I believe this makes it clearer what goes on.
>>
>
> Yes, if you only need "continue" and not "break" for a particular loop, but
> I'd just be careful not to use the word "break" to mean "continue." That
> could be confusing.
>
> Russ P.
>
> --
> http://RussP.us
>
Thu, 2009-03-19, 03:07
#45
Re: continue keyword
The time tag for each record is not known until I read and parse the record, so I don't think this will work. Even if it did, it looks more complicated to me than my continue and break statements.
Russ P.
On Wed, Mar 18, 2009 at 6:47 PM, Ricky Clarkson <ricky [dot] clarkson [at] gmail [dot] com> wrote:
--
http://RussP.us
Russ P.
On Wed, Mar 18, 2009 at 6:47 PM, Ricky Clarkson <ricky [dot] clarkson [at] gmail [dot] com> wrote:
data.takeWhile(_.time < endTime).filter(_.time > startTime).map(line
=> println("Found "+line.recordType+" at "+line.time))
Add projection to taste.
> My loop reads each data line, parses it, and processes it. If it's a blank
> line or a comment, I use "continue" to skip it. Otherwise, I need to
> determine the record type and the time tag. If the time tag preceeds the
> specified start time, I may skip it or process it, depending on the record
> type. To skip it, I use "continue." If the time tag is past the end time, I
> use "break" to terminate the loop.
>
> Now, I'm sure all that can be done without "continue" or "break," but I
> venture to say that the resulting code would be significantly more difficult
> both to write and to read.
>
>
>>
>> So a more modest extension would be to have just break. As you have
>> shown, one can model a continue by putting the breakable inside the
>> loop. I believe this makes it clearer what goes on.
>>
>
> Yes, if you only need "continue" and not "break" for a particular loop, but
> I'd just be careful not to use the word "break" to mean "continue." That
> could be confusing.
>
> Russ P.
>
> --
> http://RussP.us
>
--
http://RussP.us
Thu, 2009-03-19, 05:07
#46
Re: continue keyword
On Mar 18, 2009, at 9:47 PM, Ricky Clarkson
wrote:
> data.takeWhile(_.time < endTime).filter(_.time > startTime).map(line
> => println("Found "+line.recordType+" at "+line.time))
>
> Add projection to taste.
>
taste.add(projection)
This seems to break immutability
>> My loop reads each data line, parses it, and processes it. If it's
>> a blank
>> line or a comment, I use "continue" to skip it. Otherwise, I need to
>> determine the record type and the time tag. If the time tag
>> preceeds the
>> specified start time, I may skip it or process it, depending on the
>> record
>> type. To skip it, I use "continue." If the time tag is past the end
>> time, I
>> use "break" to terminate the loop.
>>
>> Now, I'm sure all that can be done without "continue" or "break,"
>> but I
>> venture to say that the resulting code would be significantly more
>> difficult
>> both to write and to read.
>>
>>
>>>
>>> So a more modest extension would be to have just break. As you have
>>> shown, one can model a continue by putting the breakable inside the
>>> loop. I believe this makes it clearer what goes on.
>>>
>>
>> Yes, if you only need "continue" and not "break" for a particular
>> loop, but
>> I'd just be careful not to use the word "break" to mean "continue."
>> That
>> could be confusing.
>>
>> Russ P.
>>
>> --
>> http://RussP.us
>>
Thu, 2009-03-19, 10:27
#47
Re: continue keyword
On Wed, 2009-03-18 at 13:32 -0700, Randall R Schulz wrote:
> On Wednesday March 18 2009, Russ Paielli wrote:
> > On Wed, Mar 18, 2009 at 11:58 AM, David MacIver wrote:
> > > ...
> >
> > I agree. I don't claim to be an expert on this matter, but it seems
> > to me that the three major programming "paradigms" are procedural,
> > functional, and object oriented. It also seems to me that they are
> > not mutually exclusive and can be combined in all sorts of ways.
>
> Don't forget logic programming.
And it should not be forgotten that integration of all of these
computational models has been tried previously on a number of occasions.
In particular in the period 1986-1992 there we many languages developed
integrating functional and procedural (and particularly
object-oriented). Perhaps the classic example is FOOPlog.
I agree times are now different -- we have had the functional vs. OO war
in the 1990s and it is rapidly being recognized that the religion of the
hegemony of OO was not the right result.
I have noted in some emails on this list recently a rather worrying
descent into religious zealotry and indeed rudeness. I hope the Scala
development community is not going the way of one or two notable islands
of excessive religious zeal associated with some other high-profile
programming languages.
I am on record as saying "Scala may well be what Java should have been."
I would like this to be true, and not something I regret saying.
Sorry this is not really a technical contribution, but I felt I had to
say something as some of the emails on this list I have read recently
disturbed me not for technical reasons but for social and interaction
reasons.
Thu, 2009-03-19, 11:57
#48
Re: continue keyword
2009/3/19 Christian Szegedy :
> I see your point.Indeed, this is a good example.
>
> However, I would rather have general method (let us call it foldAccum)
> of Stream[T] that generates a new stream of left folded elements for
> the first n element of the input stream (currently not in the scala stdlib).
> Then I could (still lazily) combine it with filter and first, like:
>
> myints.foldAccum(1)( _ * _).filter( _ < 1000).first
I knew you would say that. :-)
There's just one slight problem. It's wrong.
In fact, it's wrong in two regards. The first is trivial: You've
filtered by < 1000 rather than > 1000. That isn't what you meant to
do.
Let's see how this works with val xs = List(1, 2, 3, 4):
val ys = xs.foldAccum(1)(_ * _)
ys: List[Int] = List(1, 1, 2, 6, 24)
val zs = ys.filter(_ < 1000)
zs: List[Int] = List(1, 1, 2, 6, 24)
val result = zs.head
result: Int = 1
Oops. That's not what we meant to do at all, is it?
So clearly what we wanted to do is filter by > 1000.
val zs = ys.filter(_ > 1000)
zs: List[Int] = List()
scala> zs.first
java.util.NoSuchElementException
at scala.Seq$class.first(Seq.scala:199)
at scala.List.first(List.scala:452)
at .(:6)
at .()
at RequestResult$.(:4)
at RequestResult$.()
at RequestResult$result()
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(...
Hm. That doesn't work either. :-(
Want to try again? ;-)
> However, I can agree with you that for someone coming from Java this would
> look less readable and may become a bit unwieldly if things get more
> complicated.
My point has never been that this should be a crutch for Java
programmers. My point has consistently been that it adds useful
functionality and flexibility.
--j
On Tue, Mar 17, 2009 at 11:15 AM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote: