This page is no longer maintained — Please continue to the home page at www.scala-lang.org

[Fwd: Re: continue keyword]

57 replies
Eric Schwarzenbach
Joined: 2009-02-06,
User offline. Last seen 42 years 45 weeks ago.

Detering Dirk wrote:
> I would be really, really interested in seeing a simplified
> (but not oversimplified!) fully functional prototype version
> of this usecase written in your style, and than let us
> (well, not me, but the experts ;) ) show how that would be
> solved in The Scala Way.
>
> It seems a sufficiently complex, but not too complex,
> properly isolated problem for a showcase, and even coming
> out of real world necessities.
>

A hearty +1 to that!

I'm someone from the Java / traditional procedural OO world who has been
watching Scala and other functional hybrids with interest (though as yet
without time to devote to really getting my feet wet). Though by all rights
my bias should be for adding the continue and break (I've written plenty of
file parsing loops, and have used these constructs now and then), from what I've seen,
I find the alternative compelling, and actually find

data.takeWhile(_.time < endTime).filter(_.time > startTime).map(line
=> println("Found "+line.recordType+" at "+line.time))

quite comprehensible even though my grasp of Scala syntax is shaky at best.

As someone still deciding whether and to what degree to take the plunge into Scala
or FP in general, it would be EXTREMELY useful to see the non-simplified version of
this in several forms:

* The procedural without continue and break
* The procedural with continue and break (even if hypothetical)
* However many FP ways of doing it the various FP proponents think are better,
perhaps including one or more FP version using continue and break
* Perhaps a version with a bit of DSL work to soup up the readability?

It doesn't even matter if there is remotely a consensus afterwards as to which
is more readable, it would still be valuable.

Eric

Russ P.
Joined: 2009-01-31,
User offline. Last seen 1 year 26 weeks ago.
Re: [Fwd: Re: continue keyword]
Detering Dirk wrote:
> I would be really, really interested in seeing a simplified
> (but not oversimplified!) fully functional prototype version
> of this usecase written in your style, and than let us
> (well, not me, but the experts ;) ) show how that would be
> solved in The Scala Way.
>
> It seems a sufficiently complex, but not too complex,
> properly isolated problem for a showcase, and even coming
> out of real world necessities.
>

OK, you asked for it, so here is a sample for you. This is a section from one of several Python scripts I use for processing the air traffic data files I mentioned. This is the simplest of those scripts, but it has the basics. Sorry, but this section of code by itself is not fully functional. First, here is the header comment just to give you a clue what it is doing:

"""
This Python script by Russ Paielli extracts data for specified flights
and a specified time window around an operational error from a TSAFE
input data file (default: TSAFE-all.in). It puts the data into another
smaller TSAFE input file (default: TSAFE.in). By default, the aircraft
IDs of the conflict pair are specified in the input file ACpair.dat. If
the --all option is used, all flights are extracted for the specified
time period.
"""

And here is the main looping portion of the script:

count = 0

for line in file(infile): # main loop

    line = line.strip()
    if not line or line.startswith("#"): print >> out, line; continue # skip blank line or comment

    data = line.split()
    if len(data) < 3: continue # bad data line
    AC = data[2] # aircraft ID

    if ACpair and AC not in ACpair and not line.startswith("WND "): continue

    time = float(data[1]) * sec

    if time < starttime and data[0] == "TRK": continue
    if time > endtime: break

    print >> out, line

    count += 1

Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 3 days ago.
Re: [Fwd: Re: continue keyword]
This is my best shot at recreating that in Scala. I'm assuming Scalax's IO library, which is lazy.

The "skip" conditions have to be turned into "keep" conditions, but that's just a matter of applying logical NOT to them.

  import scalax.data.Implicits._
  import scalax.io.Implicits._

  case class LineTime(line: String, time: Float)

  (for {
    l <- infile.toFile.lines
    val line = l.trim
    if (line != "" && !line.startsWith("#"))

    val data = line.split(",").toList
    if data.length >= 3

    val ac = data(2)
    if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND "))

    val time = data(1).toFloat * sec
    if (time >= startTime || data(0) != "TRK")
  } yield LineTime(line, time)).takeWhile(_.time <= endTime).map(_.line)

Now, that last line is arguably a bit ugly. It'd be the only thing I'd change if break/continue were made available for Scala collections. I might make the code look like so:

  for {
    l <- infile.toFile.lines
    val line = l.trim
    if (line != "" && !line.startsWith("#"))

    val data = line.split(",").toList
    if data.length >= 3

    val ac = data(2)
    if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND "))

    val time = data(1).toFloat * sec
    if (time >= startTime || data(0) != "TRK")
    val _ = if (time > endTime) break
  } yield line

--j

On Thu, Mar 19, 2009 at 12:37 PM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote:
Detering Dirk wrote:
> I would be really, really interested in seeing a simplified
> (but not oversimplified!) fully functional prototype version
> of this usecase written in your style, and than let us
> (well, not me, but the experts ;) ) show how that would be
> solved in The Scala Way.
>
> It seems a sufficiently complex, but not too complex,
> properly isolated problem for a showcase, and even coming
> out of real world necessities.
>

OK, you asked for it, so here is a sample for you. This is a section from one of several Python scripts I use for processing the air traffic data files I mentioned. This is the simplest of those scripts, but it has the basics. Sorry, but this section of code by itself is not fully functional. First, here is the header comment just to give you a clue what it is doing:

"""
This Python script by Russ Paielli extracts data for specified flights
and a specified time window around an operational error from a TSAFE
input data file (default: TSAFE-all.in). It puts the data into another
smaller TSAFE input file (default: TSAFE.in). By default, the aircraft
IDs of the conflict pair are specified in the input file ACpair.dat. If
the --all option is used, all flights are extracted for the specified
time period.
"""

And here is the main looping portion of the script:

count = 0

for line in file(infile): # main loop

    line = line.strip()
    if not line or line.startswith("#"): print >> out, line; continue # skip blank line or comment

    data = line.split()
    if len(data) < 3: continue # bad data line
    AC = data[2] # aircraft ID

    if ACpair and AC not in ACpair and not line.startswith("WND "): continue

    time = float(data[1]) * sec

    if time < starttime and data[0] == "TRK": continue
    if time > endtime: break

    print >> out, line

    count += 1


Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 3 days ago.
Re: [Fwd: Re: continue keyword]
Oops, my split should split on whitespace, not commas. It's been a while since I did Python, sorry.

--j

On Thu, Mar 19, 2009 at 1:03 PM, Jorge Ortiz <jorge [dot] ortiz [at] gmail [dot] com> wrote:
This is my best shot at recreating that in Scala. I'm assuming Scalax's IO library, which is lazy.

The "skip" conditions have to be turned into "keep" conditions, but that's just a matter of applying logical NOT to them.

  import scalax.data.Implicits._
  import scalax.io.Implicits._

  case class LineTime(line: String, time: Float)

  (for {
    l <- infile.toFile.lines
    val line = l.trim
    if (line != "" && !line.startsWith("#"))

    val data = line.split(",").toList
    if data.length >= 3

    val ac = data(2)
    if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND "))

    val time = data(1).toFloat * sec
    if (time >= startTime || data(0) != "TRK")
  } yield LineTime(line, time)).takeWhile(_.time <= endTime).map(_.line)

Now, that last line is arguably a bit ugly. It'd be the only thing I'd change if break/continue were made available for Scala collections. I might make the code look like so:

  for {
    l <- infile.toFile.lines
    val line = l.trim
    if (line != "" && !line.startsWith("#"))

    val data = line.split(",").toList
    if data.length >= 3

    val ac = data(2)
    if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND "))

    val time = data(1).toFloat * sec
    if (time >= startTime || data(0) != "TRK")
    val _ = if (time > endTime) break
  } yield line

--j

On Thu, Mar 19, 2009 at 12:37 PM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote:
Detering Dirk wrote:
> I would be really, really interested in seeing a simplified
> (but not oversimplified!) fully functional prototype version
> of this usecase written in your style, and than let us
> (well, not me, but the experts ;) ) show how that would be
> solved in The Scala Way.
>
> It seems a sufficiently complex, but not too complex,
> properly isolated problem for a showcase, and even coming
> out of real world necessities.
>

OK, you asked for it, so here is a sample for you. This is a section from one of several Python scripts I use for processing the air traffic data files I mentioned. This is the simplest of those scripts, but it has the basics. Sorry, but this section of code by itself is not fully functional. First, here is the header comment just to give you a clue what it is doing:

"""
This Python script by Russ Paielli extracts data for specified flights
and a specified time window around an operational error from a TSAFE
input data file (default: TSAFE-all.in). It puts the data into another
smaller TSAFE input file (default: TSAFE.in). By default, the aircraft
IDs of the conflict pair are specified in the input file ACpair.dat. If
the --all option is used, all flights are extracted for the specified
time period.
"""

And here is the main looping portion of the script:

count = 0

for line in file(infile): # main loop

    line = line.strip()
    if not line or line.startswith("#"): print >> out, line; continue # skip blank line or comment

    data = line.split()
    if len(data) < 3: continue # bad data line
    AC = data[2] # aircraft ID

    if ACpair and AC not in ACpair and not line.startswith("WND "): continue

    time = float(data[1]) * sec

    if time < starttime and data[0] == "TRK": continue
    if time > endtime: break

    print >> out, line

    count += 1



Russ P.
Joined: 2009-01-31,
User offline. Last seen 1 year 26 weeks ago.
Re: [Fwd: Re: continue keyword]
Wow, that was fast! I doubt your first cut is completely correct, but it's probably "close enough for government work," as they say. You're obviously a very proficient Scala programmer.

But here's an important point. Your approach would have been much harder for me (and most other non-experts in Scala) to program than the simple break/continue version. Now, if this were critical production code, you could conceivably make a case that it shouldn't use break or continue (I don't think I would buy it, but you could make the case). But this is not critical production code. It is simply a utility for converting an input file for research purposes. So why should I be forced to do it the harder way, without break or continue? In this case, I just want something that llooks reasonable and works so I can move on to more important issues.

Russ P.

On Thu, Mar 19, 2009 at 1:03 PM, Jorge Ortiz <jorge [dot] ortiz [at] gmail [dot] com> wrote:
This is my best shot at recreating that in Scala. I'm assuming Scalax's IO library, which is lazy.

The "skip" conditions have to be turned into "keep" conditions, but that's just a matter of applying logical NOT to them.

  import scalax.data.Implicits._
  import scalax.io.Implicits._

  case class LineTime(line: String, time: Float)

  (for {
    l <- infile.toFile.lines
    val line = l.trim
    if (line != "" && !line.startsWith("#"))

    val data = line.split(",").toList
    if data.length >= 3

    val ac = data(2)
    if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND "))

    val time = data(1).toFloat * sec
    if (time >= startTime || data(0) != "TRK")
  } yield LineTime(line, time)).takeWhile(_.time <= endTime).map(_.line)

Now, that last line is arguably a bit ugly. It'd be the only thing I'd change if break/continue were made available for Scala collections. I might make the code look like so:

  for {
    l <- infile.toFile.lines
    val line = l.trim
    if (line != "" && !line.startsWith("#"))

    val data = line.split(",").toList
    if data.length >= 3

    val ac = data(2)
    if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND "))

    val time = data(1).toFloat * sec
    if (time >= startTime || data(0) != "TRK")
    val _ = if (time > endTime) break
  } yield line

--j

On Thu, Mar 19, 2009 at 12:37 PM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote:
Detering Dirk wrote:
> I would be really, really interested in seeing a simplified
> (but not oversimplified!) fully functional prototype version
> of this usecase written in your style, and than let us
> (well, not me, but the experts ;) ) show how that would be
> solved in The Scala Way.
>
> It seems a sufficiently complex, but not too complex,
> properly isolated problem for a showcase, and even coming
> out of real world necessities.
>

OK, you asked for it, so here is a sample for you. This is a section from one of several Python scripts I use for processing the air traffic data files I mentioned. This is the simplest of those scripts, but it has the basics. Sorry, but this section of code by itself is not fully functional. First, here is the header comment just to give you a clue what it is doing:

"""
This Python script by Russ Paielli extracts data for specified flights
and a specified time window around an operational error from a TSAFE
input data file (default: TSAFE-all.in). It puts the data into another
smaller TSAFE input file (default: TSAFE.in). By default, the aircraft
IDs of the conflict pair are specified in the input file ACpair.dat. If
the --all option is used, all flights are extracted for the specified
time period.
"""

And here is the main looping portion of the script:

count = 0

for line in file(infile): # main loop

    line = line.strip()
    if not line or line.startswith("#"): print >> out, line; continue # skip blank line or comment

    data = line.split()
    if len(data) < 3: continue # bad data line
    AC = data[2] # aircraft ID

    if ACpair and AC not in ACpair and not line.startswith("WND "): continue

    time = float(data[1]) * sec

    if time < starttime and data[0] == "TRK": continue
    if time > endtime: break

    print >> out, line

    count += 1





--
http://RussP.us
David Hall 3
Joined: 2009-02-19,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

On Thu, Mar 19, 2009 at 1:03 PM, Jorge Ortiz wrote:
>     val _ = if (time > endTime) break

Is there any way to make lines like this cleaner? I use them
occasionally and I'm always kind of annoyed by the "val _ =" or "() ="
noise.

If not, how would people feel about something like

do if (time > endTime) break

?

vpatryshev
Joined: 2009-02-16,
User offline. Last seen 1 year 24 weeks ago.
Re: [Fwd: Re: continue keyword]
I think the trick is that if there is a good idea or solution, you learn it only once, but you save a lot on applying it many times afterwards. And even if learning looks hard before you do it... it does not look so hard when you are done.

2009/3/19 Russ Paielli <russ [dot] paielli [at] gmail [dot] com>
Wow, that was fast! I doubt your first cut is completely correct, but it's probably "close enough for government work," as they say. You're obviously a very proficient Scala programmer.

But here's an important point. Your approach would have been much harder for me (and most other non-experts in Scala) to program than the simple break/continue version. Now, if this were critical production code, you could conceivably make a case that it shouldn't use break or continue (I don't think I would buy it, but you could make the case). But this is not critical production code. It is simply a utility for converting an input file for research purposes. So why should I be forced to do it the harder way, without break or continue? In this case, I just want something that llooks reasonable and works so I can move on to more important issues.

Russ P.

On Thu, Mar 19, 2009 at 1:03 PM, Jorge Ortiz <jorge [dot] ortiz [at] gmail [dot] com> wrote:
This is my best shot at recreating that in Scala. I'm assuming Scalax's IO library, which is lazy.

The "skip" conditions have to be turned into "keep" conditions, but that's just a matter of applying logical NOT to them.

  import scalax.data.Implicits._
  import scalax.io.Implicits._

  case class LineTime(line: String, time: Float)

  (for {
    l <- infile.toFile.lines
    val line = l.trim
    if (line != "" && !line.startsWith("#"))

    val data = line.split(",").toList
    if data.length >= 3

    val ac = data(2)
    if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND "))

    val time = data(1).toFloat * sec
    if (time >= startTime || data(0) != "TRK")
  } yield LineTime(line, time)).takeWhile(_.time <= endTime).map(_.line)

Now, that last line is arguably a bit ugly. It'd be the only thing I'd change if break/continue were made available for Scala collections. I might make the code look like so:

  for {
    l <- infile.toFile.lines
    val line = l.trim
    if (line != "" && !line.startsWith("#"))

    val data = line.split(",").toList
    if data.length >= 3

    val ac = data(2)
    if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND "))

    val time = data(1).toFloat * sec
    if (time >= startTime || data(0) != "TRK")
    val _ = if (time > endTime) break
  } yield line

--j

On Thu, Mar 19, 2009 at 12:37 PM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote:
Detering Dirk wrote:
> I would be really, really interested in seeing a simplified
> (but not oversimplified!) fully functional prototype version
> of this usecase written in your style, and than let us
> (well, not me, but the experts ;) ) show how that would be
> solved in The Scala Way.
>
> It seems a sufficiently complex, but not too complex,
> properly isolated problem for a showcase, and even coming
> out of real world necessities.
>

OK, you asked for it, so here is a sample for you. This is a section from one of several Python scripts I use for processing the air traffic data files I mentioned. This is the simplest of those scripts, but it has the basics. Sorry, but this section of code by itself is not fully functional. First, here is the header comment just to give you a clue what it is doing:

"""
This Python script by Russ Paielli extracts data for specified flights
and a specified time window around an operational error from a TSAFE
input data file (default: TSAFE-all.in). It puts the data into another
smaller TSAFE input file (default: TSAFE.in). By default, the aircraft
IDs of the conflict pair are specified in the input file ACpair.dat. If
the --all option is used, all flights are extracted for the specified
time period.
"""

And here is the main looping portion of the script:

count = 0

for line in file(infile): # main loop

    line = line.strip()
    if not line or line.startswith("#"): print >> out, line; continue # skip blank line or comment

    data = line.split()
    if len(data) < 3: continue # bad data line
    AC = data[2] # aircraft ID

    if ACpair and AC not in ACpair and not line.startswith("WND "): continue

    time = float(data[1]) * sec

    if time < starttime and data[0] == "TRK": continue
    if time > endtime: break

    print >> out, line

    count += 1





--
http://RussP.us



--
Thanks,
-Vlad
Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 3 days ago.
Re: [Fwd: Re: continue keyword]
Actually, David MacIver's suggestion incorporates break as a library. There is no change to the parser, or any part of the compiler. Just the standard library.

--j

On Thu, Mar 19, 2009 at 1:40 PM, Christian Szegedy <christian [dot] szegedy [at] gmail [dot] com> wrote:
Wow, this is very insightful and intriguing suggestion.

Since for comprehensions practically desugared into flatMaps and
filters (the latter practically enables the the support for continue)
your suggestion could be taken as a new sugar to incorporate
takeWhiles in for loops.

The drawback is that it requires a change to the parser, but it is the
most functional spirited suggestion I have read in this thread.


On 3/19/09, Jorge Ortiz <jorge [dot] ortiz [at] gmail [dot] com> wrote:
> Now, that last line is arguably a bit ugly. It'd be the only thing I'd
> change if break/continue were made available for Scala collections. I might
> make the code look like so:
>
>   for {
>     l <- infile.toFile.lines
>     val line = l.trim
>     if (line != "" && !line.startsWith("#"))
>
>     val data = line.split(",").toList
>     if data.length >= 3
>
>     val ac = data(2)
>     if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND "))
>
>     val time = data(1).toFloat * sec
>     if (time >= startTime || data(0) != "TRK")
>      val _ = if (time > endTime) break
>   } yield line
>

Christian Szegedy
Joined: 2009-02-08,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

Wow, this is very insightful and intriguing suggestion.

Since for comprehensions practically desugared into flatMaps and
filters (the latter practically enables the the support for continue)
your suggestion could be taken as a new sugar to incorporate
takeWhiles in for loops.

The drawback is that it requires a change to the parser, but it is the
most functional spirited suggestion I have read in this thread.

On 3/19/09, Jorge Ortiz wrote:
> Now, that last line is arguably a bit ugly. It'd be the only thing I'd
> change if break/continue were made available for Scala collections. I might
> make the code look like so:
>
> for {
> l <- infile.toFile.lines
> val line = l.trim
> if (line != "" && !line.startsWith("#"))
>
> val data = line.split(",").toList
> if data.length >= 3
>
> val ac = data(2)
> if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND "))
>
> val time = data(1).toFloat * sec
> if (time >= startTime || data(0) != "TRK")
> val _ = if (time > endTime) break
> } yield line
>

Christian Szegedy
Joined: 2009-02-08,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

I understand David's suggestion, but I find the solution of
reinterpreting break statements as simple syntax sugar for takeWhiles
without the ad-hoc use of exceptions as much more pleasing from a
theoretical point of view. It is also practical, since it limits the
way they could be abused.

Additionally, it fits very nicely with the purely functional
philosophy. Also, It would extend scala's for-comprehension framework
in a consistent way.

On 3/19/09, Jorge Ortiz wrote:
> Actually, David MacIver's suggestion incorporates break as a library. There
> is no change to the parser, or any part of the compiler. Just the standard
> library.
>
> --j
>
>
> On Thu, Mar 19, 2009 at 1:40 PM, Christian Szegedy
> wrote:
>
> > Wow, this is very insightful and intriguing suggestion.
> >
> > Since for comprehensions practically desugared into flatMaps and
> > filters (the latter practically enables the the support for continue)
> > your suggestion could be taken as a new sugar to incorporate
> > takeWhiles in for loops.
> >
> > The drawback is that it requires a change to the parser, but it is the
> > most functional spirited suggestion I have read in this thread.
> >
> >
> >
> >
> >
> > On 3/19/09, Jorge Ortiz wrote:
> > > Now, that last line is arguably a bit ugly. It'd be the only thing I'd
> > > change if break/continue were made available for Scala collections. I
> might
> > > make the code look like so:
> > >
> > > for {
> > > l <- infile.toFile.lines
> > > val line = l.trim
> > > if (line != "" && !line.startsWith("#"))
> > >
> > > val data = line.split(",").toList
> > > if data.length >= 3
> > >
> > > val ac = data(2)
> > > if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND
> "))
> > >
> > > val time = data(1).toFloat * sec
> > > if (time >= startTime || data(0) != "TRK")
> > > val _ = if (time > endTime) break
> > > } yield line
> > >
> >
>
>

Martin S. Weber
Joined: 2008-12-23,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

Quoting Jorge Ortiz :

> (for {
> l <- infile.toFile.lines
> val line = l.trim
> if (line != "" && !line.startsWith("#"))
(snip snap)
>> if not line or line.startswith("#"): print >> out, line; continue #
(snappitysnap)

As you can see above, the line is copied without further processing.
So your yielded stuff would have to include the empty or comment
lines, but without further date or data checking. This is one point
where continue comes handy imo..

Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 3 days ago.
Re: [Fwd: Re: continue keyword]
He's printing, not yielding.

I could easily print.

Or do some other side-effecting thing like appending to a Buffer of lines.

--j

On Thu, Mar 19, 2009 at 2:28 PM, Martin S. Weber <martin [dot] weber [at] nist [dot] gov> wrote:
Quoting Jorge Ortiz <jorge [dot] ortiz [at] gmail [dot] com>:

 (for {
   l <- infile.toFile.lines
   val line = l.trim
   if (line != "" && !line.startsWith("#"))
(snip snap)
   if not line or line.startswith("#"): print >> out, line; continue #
(snappitysnap)

As you can see above, the line is copied without further processing. So your yielded stuff would have to include the empty or comment lines, but without further date or data checking. This is one point where continue comes handy imo..

Carsten Saager
Joined: 2008-12-19,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]
Cool, but entirely incompatible with coding standards that tell you to put any logic into the body of the loop.

You fired from the Java team!

Lucky Bastard ...

-Carsten

On Thu, Mar 19, 2009 at 9:03 PM, Jorge Ortiz <jorge [dot] ortiz [at] gmail [dot] com> wrote:
This is my best shot at recreating that in Scala. I'm assuming Scalax's IO library, which is lazy.

The "skip" conditions have to be turned into "keep" conditions, but that's just a matter of applying logical NOT to them.

  import scalax.data.Implicits._
  import scalax.io.Implicits._

  case class LineTime(line: String, time: Float)

  (for {
    l <- infile.toFile.lines
    val line = l.trim
    if (line != "" && !line.startsWith("#"))

    val data = line.split(",").toList
    if data.length >= 3

    val ac = data(2)
    if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND "))

    val time = data(1).toFloat * sec
    if (time >= startTime || data(0) != "TRK")
  } yield LineTime(line, time)).takeWhile(_.time <= endTime).map(_.line)

Now, that last line is arguably a bit ugly. It'd be the only thing I'd change if break/continue were made available for Scala collections. I might make the code look like so:

  for {
    l <- infile.toFile.lines
    val line = l.trim
    if (line != "" && !line.startsWith("#"))

    val data = line.split(",").toList
    if data.length >= 3

    val ac = data(2)
    if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND "))

    val time = data(1).toFloat * sec
    if (time >= startTime || data(0) != "TRK")
    val _ = if (time > endTime) break
  } yield line

--j

On Thu, Mar 19, 2009 at 12:37 PM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote:
Detering Dirk wrote:
> I would be really, really interested in seeing a simplified
> (but not oversimplified!) fully functional prototype version
> of this usecase written in your style, and than let us
> (well, not me, but the experts ;) ) show how that would be
> solved in The Scala Way.
>
> It seems a sufficiently complex, but not too complex,
> properly isolated problem for a showcase, and even coming
> out of real world necessities.
>

OK, you asked for it, so here is a sample for you. This is a section from one of several Python scripts I use for processing the air traffic data files I mentioned. This is the simplest of those scripts, but it has the basics. Sorry, but this section of code by itself is not fully functional. First, here is the header comment just to give you a clue what it is doing:

"""
This Python script by Russ Paielli extracts data for specified flights
and a specified time window around an operational error from a TSAFE
input data file (default: TSAFE-all.in). It puts the data into another
smaller TSAFE input file (default: TSAFE.in). By default, the aircraft
IDs of the conflict pair are specified in the input file ACpair.dat. If
the --all option is used, all flights are extracted for the specified
time period.
"""

And here is the main looping portion of the script:

count = 0

for line in file(infile): # main loop

    line = line.strip()
    if not line or line.startswith("#"): print >> out, line; continue # skip blank line or comment

    data = line.split()
    if len(data) < 3: continue # bad data line
    AC = data[2] # aircraft ID

    if ACpair and AC not in ACpair and not line.startswith("WND "): continue

    time = float(data[1]) * sec

    if time < starttime and data[0] == "TRK": continue
    if time > endtime: break

    print >> out, line

    count += 1



Chris Twiner
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

wow that would be a crazy standard, the python code loops on logic
(for each line in file), for loops would be out as all three elements
of control are logic. while(true) only??

on a serious note have you actually seen a standard like this? what
kind of examples do they give for good loops and for bad loops?

On Thu, Mar 19, 2009 at 11:45 PM, Carsten Saager wrote:
> Cool, but entirely incompatible with coding standards that tell you to put
> any logic into the body of the loop.
>
> You fired from the Java team!
>
> Lucky Bastard ...
>
> -Carsten
>
> On Thu, Mar 19, 2009 at 9:03 PM, Jorge Ortiz wrote:
>>
>> This is my best shot at recreating that in Scala. I'm assuming Scalax's IO
>> library, which is lazy.
>>
>> The "skip" conditions have to be turned into "keep" conditions, but that's
>> just a matter of applying logical NOT to them.
>>
>>   import scalax.data.Implicits._
>>   import scalax.io.Implicits._
>>
>>   case class LineTime(line: String, time: Float)
>>
>>   (for {
>>     l <- infile.toFile.lines
>>     val line = l.trim
>>     if (line != "" && !line.startsWith("#"))
>>
>>     val data = line.split(",").toList
>>     if data.length >= 3
>>
>>     val ac = data(2)
>>     if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND
>> "))
>>
>>     val time = data(1).toFloat * sec
>>     if (time >= startTime || data(0) != "TRK")
>>   } yield LineTime(line, time)).takeWhile(_.time <= endTime).map(_.line)
>>
>> Now, that last line is arguably a bit ugly. It'd be the only thing I'd
>> change if break/continue were made available for Scala collections. I might
>> make the code look like so:
>>
>>   for {
>>     l <- infile.toFile.lines
>>     val line = l.trim
>>     if (line != "" && !line.startsWith("#"))
>>
>>     val data = line.split(",").toList
>>     if data.length >= 3
>>
>>     val ac = data(2)
>>     if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND
>> "))
>>
>>     val time = data(1).toFloat * sec
>>     if (time >= startTime || data(0) != "TRK")
>>     val _ = if (time > endTime) break
>>   } yield line
>>
>> --j
>>
>> On Thu, Mar 19, 2009 at 12:37 PM, Russ Paielli
>> wrote:
>>>
>>> Detering Dirk wrote:
>>> > I would be really, really interested in seeing a simplified
>>> > (but not oversimplified!) fully functional prototype version
>>> > of this usecase written in your style, and than let us
>>> > (well, not me, but the experts ;) ) show how that would be
>>> > solved in The Scala Way.
>>> >
>>> > It seems a sufficiently complex, but not too complex,
>>> > properly isolated problem for a showcase, and even coming
>>> > out of real world necessities.
>>> >
>>>
>>> OK, you asked for it, so here is a sample for you. This is a section from
>>> one of several Python scripts I use for processing the air traffic data
>>> files I mentioned. This is the simplest of those scripts, but it has the
>>> basics. Sorry, but this section of code by itself is not fully functional.
>>> First, here is the header comment just to give you a clue what it is doing:
>>>
>>> """
>>> This Python script by Russ Paielli extracts data for specified flights
>>> and a specified time window around an operational error from a TSAFE
>>> input data file (default: TSAFE-all.in). It puts the data into another
>>> smaller TSAFE input file (default: TSAFE.in). By default, the aircraft
>>> IDs of the conflict pair are specified in the input file ACpair.dat. If
>>> the --all option is used, all flights are extracted for the specified
>>> time period.
>>> """
>>>
>>> And here is the main looping portion of the script:
>>>
>>> count = 0
>>>
>>> for line in file(infile): # main loop
>>>
>>>     line = line.strip()
>>>     if not line or line.startswith("#"): print >> out, line; continue #
>>> skip blank line or comment
>>>
>>>     data = line.split()
>>>     if len(data) < 3: continue # bad data line
>>>     AC = data[2] # aircraft ID
>>>
>>>     if ACpair and AC not in ACpair and not line.startswith("WND "):
>>> continue
>>>
>>>     time = float(data[1]) * sec
>>>
>>>     if time < starttime and data[0] == "TRK": continue
>>>     if time > endtime: break
>>>
>>>     print >> out, line
>>>
>>>     count += 1
>>>
>>
>
>

Carsten Saager
Joined: 2008-12-19,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]
If you happen to find my CV you'll come across the name of a company I worked for five years ago. Since then my stance on coding standards is to ignore them and stay away from groups that define them.

To be fair, these standards had been derived from C-coding standards to have C++ standards. Extrapolating this to Scala would be complete nonsense and Jorge's code is the perfect example why.

I also have some Java coding standards on my disk that I happily ignore for several years now. To get an idea, think of the Sun standard with all non Java specifics replaced by something that originates in Pascal. Add deliberately the MS naming conventions to have a real disgusting taste.

Someone told me that they have the convention that code is indented by 8 and all comments start at the first col. Sounds familiar?

If it is already hard to adapt formal criteria for code, how hard (and slow)  will it be to change the thinking?

-Carsten


On Thu, Mar 19, 2009 at 11:51 PM, Chris Twiner <chris [dot] twiner [at] gmail [dot] com> wrote:
wow that would be a crazy standard, the python code loops on logic
(for each line in file), for loops would be out as all three elements
of control are logic.  while(true) only??

on a serious note have you actually seen a standard like this?  what
kind of examples do they give for good loops and for bad loops?

On Thu, Mar 19, 2009 at 11:45 PM, Carsten Saager <csaager [at] gmail [dot] com> wrote:
> Cool, but entirely incompatible with coding standards that tell you to put
> any logic into the body of the loop.
>
> You fired from the Java team!
>
> Lucky Bastard ...
>
> -Carsten
>
> On Thu, Mar 19, 2009 at 9:03 PM, Jorge Ortiz <jorge [dot] ortiz [at] gmail [dot] com> wrote:
>>
>> This is my best shot at recreating that in Scala. I'm assuming Scalax's IO
>> library, which is lazy.
>>
>> The "skip" conditions have to be turned into "keep" conditions, but that's
>> just a matter of applying logical NOT to them.
>>
>>   import scalax.data.Implicits._
>>   import scalax.io.Implicits._
>>
>>   case class LineTime(line: String, time: Float)
>>
>>   (for {
>>     l <- infile.toFile.lines
>>     val line = l.trim
>>     if (line != "" && !line.startsWith("#"))
>>
>>     val data = line.split(",").toList
>>     if data.length >= 3
>>
>>     val ac = data(2)
>>     if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND
>> "))
>>
>>     val time = data(1).toFloat * sec
>>     if (time >= startTime || data(0) != "TRK")
>>   } yield LineTime(line, time)).takeWhile(_.time <= endTime).map(_.line)
>>
>> Now, that last line is arguably a bit ugly. It'd be the only thing I'd
>> change if break/continue were made available for Scala collections. I might
>> make the code look like so:
>>
>>   for {
>>     l <- infile.toFile.lines
>>     val line = l.trim
>>     if (line != "" && !line.startsWith("#"))
>>
>>     val data = line.split(",").toList
>>     if data.length >= 3
>>
>>     val ac = data(2)
>>     if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND
>> "))
>>
>>     val time = data(1).toFloat * sec
>>     if (time >= startTime || data(0) != "TRK")
>>     val _ = if (time > endTime) break
>>   } yield line
>>
>> --j
>>
>> On Thu, Mar 19, 2009 at 12:37 PM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com>
>> wrote:
>>>
>>> Detering Dirk wrote:
>>> > I would be really, really interested in seeing a simplified
>>> > (but not oversimplified!) fully functional prototype version
>>> > of this usecase written in your style, and than let us
>>> > (well, not me, but the experts ;) ) show how that would be
>>> > solved in The Scala Way.
>>> >
>>> > It seems a sufficiently complex, but not too complex,
>>> > properly isolated problem for a showcase, and even coming
>>> > out of real world necessities.
>>> >
>>>
>>> OK, you asked for it, so here is a sample for you. This is a section from
>>> one of several Python scripts I use for processing the air traffic data
>>> files I mentioned. This is the simplest of those scripts, but it has the
>>> basics. Sorry, but this section of code by itself is not fully functional.
>>> First, here is the header comment just to give you a clue what it is doing:
>>>
>>> """
>>> This Python script by Russ Paielli extracts data for specified flights
>>> and a specified time window around an operational error from a TSAFE
>>> input data file (default: TSAFE-all.in). It puts the data into another
>>> smaller TSAFE input file (default: TSAFE.in). By default, the aircraft
>>> IDs of the conflict pair are specified in the input file ACpair.dat. If
>>> the --all option is used, all flights are extracted for the specified
>>> time period.
>>> """
>>>
>>> And here is the main looping portion of the script:
>>>
>>> count = 0
>>>
>>> for line in file(infile): # main loop
>>>
>>>     line = line.strip()
>>>     if not line or line.startswith("#"): print >> out, line; continue #
>>> skip blank line or comment
>>>
>>>     data = line.split()
>>>     if len(data) < 3: continue # bad data line
>>>     AC = data[2] # aircraft ID
>>>
>>>     if ACpair and AC not in ACpair and not line.startswith("WND "):
>>> continue
>>>
>>>     time = float(data[1]) * sec
>>>
>>>     if time < starttime and data[0] == "TRK": continue
>>>     if time > endtime: break
>>>
>>>     print >> out, line
>>>
>>>     count += 1
>>>
>>
>
>

vpatryshev
Joined: 2009-02-16,
User offline. Last seen 1 year 24 weeks ago.
Re: [Fwd: Re: continue keyword]
Sounds familiar. I remember a year ago my coworkers were very strongly suggesting me to use OOP instead of FP style in JavaScript, and use monstrosities like bind() instead of plain closures; their reason was that EcmaScript 4 will be adopted soon that legalizes OOP in JavaScript (the actual reason was that people never saw FP before, being plain vanilla Java programmers).
My point is: forget Java as you forgot C. Move on.

2009/3/19 Carsten Saager <csaager [at] gmail [dot] com>
If you happen to find my CV you'll come across the name of a company I worked for five years ago. Since then my stance on coding standards is to ignore them and stay away from groups that define them.

To be fair, these standards had been derived from C-coding standards to have C++ standards. Extrapolating this to Scala would be complete nonsense and Jorge's code is the perfect example why.

I also have some Java coding standards on my disk that I happily ignore for several years now. To get an idea, think of the Sun standard with all non Java specifics replaced by something that originates in Pascal. Add deliberately the MS naming conventions to have a real disgusting taste.

Someone told me that they have the convention that code is indented by 8 and all comments start at the first col. Sounds familiar?

If it is already hard to adapt formal criteria for code, how hard (and slow)  will it be to change the thinking?

-Carsten


On Thu, Mar 19, 2009 at 11:51 PM, Chris Twiner <chris [dot] twiner [at] gmail [dot] com> wrote:
wow that would be a crazy standard, the python code loops on logic
(for each line in file), for loops would be out as all three elements
of control are logic.  while(true) only??

on a serious note have you actually seen a standard like this?  what
kind of examples do they give for good loops and for bad loops?

On Thu, Mar 19, 2009 at 11:45 PM, Carsten Saager <csaager [at] gmail [dot] com> wrote:
> Cool, but entirely incompatible with coding standards that tell you to put
> any logic into the body of the loop.
>
> You fired from the Java team!
>
> Lucky Bastard ...
>
> -Carsten
>
> On Thu, Mar 19, 2009 at 9:03 PM, Jorge Ortiz <jorge [dot] ortiz [at] gmail [dot] com> wrote:
>>
>> This is my best shot at recreating that in Scala. I'm assuming Scalax's IO
>> library, which is lazy.
>>
>> The "skip" conditions have to be turned into "keep" conditions, but that's
>> just a matter of applying logical NOT to them.
>>
>>   import scalax.data.Implicits._
>>   import scalax.io.Implicits._
>>
>>   case class LineTime(line: String, time: Float)
>>
>>   (for {
>>     l <- infile.toFile.lines
>>     val line = l.trim
>>     if (line != "" && !line.startsWith("#"))
>>
>>     val data = line.split(",").toList
>>     if data.length >= 3
>>
>>     val ac = data(2)
>>     if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND
>> "))
>>
>>     val time = data(1).toFloat * sec
>>     if (time >= startTime || data(0) != "TRK")
>>   } yield LineTime(line, time)).takeWhile(_.time <= endTime).map(_.line)
>>
>> Now, that last line is arguably a bit ugly. It'd be the only thing I'd
>> change if break/continue were made available for Scala collections. I might
>> make the code look like so:
>>
>>   for {
>>     l <- infile.toFile.lines
>>     val line = l.trim
>>     if (line != "" && !line.startsWith("#"))
>>
>>     val data = line.split(",").toList
>>     if data.length >= 3
>>
>>     val ac = data(2)
>>     if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND
>> "))
>>
>>     val time = data(1).toFloat * sec
>>     if (time >= startTime || data(0) != "TRK")
>>     val _ = if (time > endTime) break
>>   } yield line
>>
>> --j
>>
>> On Thu, Mar 19, 2009 at 12:37 PM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com>
>> wrote:
>>>
>>> Detering Dirk wrote:
>>> > I would be really, really interested in seeing a simplified
>>> > (but not oversimplified!) fully functional prototype version
>>> > of this usecase written in your style, and than let us
>>> > (well, not me, but the experts ;) ) show how that would be
>>> > solved in The Scala Way.
>>> >
>>> > It seems a sufficiently complex, but not too complex,
>>> > properly isolated problem for a showcase, and even coming
>>> > out of real world necessities.
>>> >
>>>
>>> OK, you asked for it, so here is a sample for you. This is a section from
>>> one of several Python scripts I use for processing the air traffic data
>>> files I mentioned. This is the simplest of those scripts, but it has the
>>> basics. Sorry, but this section of code by itself is not fully functional.
>>> First, here is the header comment just to give you a clue what it is doing:
>>>
>>> """
>>> This Python script by Russ Paielli extracts data for specified flights
>>> and a specified time window around an operational error from a TSAFE
>>> input data file (default: TSAFE-all.in). It puts the data into another
>>> smaller TSAFE input file (default: TSAFE.in). By default, the aircraft
>>> IDs of the conflict pair are specified in the input file ACpair.dat. If
>>> the --all option is used, all flights are extracted for the specified
>>> time period.
>>> """
>>>
>>> And here is the main looping portion of the script:
>>>
>>> count = 0
>>>
>>> for line in file(infile): # main loop
>>>
>>>     line = line.strip()
>>>     if not line or line.startswith("#"): print >> out, line; continue #
>>> skip blank line or comment
>>>
>>>     data = line.split()
>>>     if len(data) < 3: continue # bad data line
>>>     AC = data[2] # aircraft ID
>>>
>>>     if ACpair and AC not in ACpair and not line.startswith("WND "):
>>> continue
>>>
>>>     time = float(data[1]) * sec
>>>
>>>     if time < starttime and data[0] == "TRK": continue
>>>     if time > endtime: break
>>>
>>>     print >> out, line
>>>
>>>     count += 1
>>>
>>
>
>




--
Thanks,
-Vlad
milessabin
Joined: 2008-08-11,
User offline. Last seen 33 weeks 3 days ago.
Re: [Fwd: Re: continue keyword]

On Thu, Mar 19, 2009 at 11:40 PM, Vlad Patryshev wrote:
> Sounds familiar. I remember a year ago my coworkers were very strongly
> suggesting me to use OOP instead of FP style in JavaScript, and use
> monstrosities like bind() instead of plain closures; their reason was that
> EcmaScript 4 will be adopted soon that legalizes OOP in JavaScript (the
> actual reason was that people never saw FP before, being plain vanilla Java
> programmers).
> My point is: forget Java as you forgot C. Move on.

Scala is a language which quite deliberately mixes object oriented and
and functional programming styles and which trades very heavily on
it's ability to interoperate with Java.

If you want to forget OOP in general and Java in particular then I
suggest you go elsewhere.

Cheers,

Miles

Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: [Fwd: Re: continue keyword]
I believe some coding standards are necessary.  Like "Put your source in this directory and the ant build will compile it", or "use spaces instead of tabs, so our version history doesn't freak out".    These tend to be practical things the help out when using existing tools.  Some are even nice to attempt to avoid bugs like "never synchronize on a java string".  However it's when these go too far that they become bad, and I believe many people try to take these things too far.  I received a B in a college course because I refused to follow the 7 page coding standard, mostly because I disagreed with the principle behind a lot of the rules in the standard.  However don't throw the bathwater out with the baby on this.  Use standards that are practical, otherwise chaos will wreak havoc on your project.

-Josh

P.S. Hopefully after butchering turns of phrase, more people will use them incorrectly.

On Thu, Mar 19, 2009 at 7:40 PM, Vlad Patryshev <vpatryshev [at] gmail [dot] com> wrote:
Sounds familiar. I remember a year ago my coworkers were very strongly suggesting me to use OOP instead of FP style in JavaScript, and use monstrosities like bind() instead of plain closures; their reason was that EcmaScript 4 will be adopted soon that legalizes OOP in JavaScript (the actual reason was that people never saw FP before, being plain vanilla Java programmers).
My point is: forget Java as you forgot C. Move on.

2009/3/19 Carsten Saager <csaager [at] gmail [dot] com>
If you happen to find my CV you'll come across the name of a company I worked for five years ago. Since then my stance on coding standards is to ignore them and stay away from groups that define them.

To be fair, these standards had been derived from C-coding standards to have C++ standards. Extrapolating this to Scala would be complete nonsense and Jorge's code is the perfect example why.

I also have some Java coding standards on my disk that I happily ignore for several years now. To get an idea, think of the Sun standard with all non Java specifics replaced by something that originates in Pascal. Add deliberately the MS naming conventions to have a real disgusting taste.

Someone told me that they have the convention that code is indented by 8 and all comments start at the first col. Sounds familiar?

If it is already hard to adapt formal criteria for code, how hard (and slow)  will it be to change the thinking?

-Carsten


On Thu, Mar 19, 2009 at 11:51 PM, Chris Twiner <chris [dot] twiner [at] gmail [dot] com> wrote:
wow that would be a crazy standard, the python code loops on logic
(for each line in file), for loops would be out as all three elements
of control are logic.  while(true) only??

on a serious note have you actually seen a standard like this?  what
kind of examples do they give for good loops and for bad loops?

On Thu, Mar 19, 2009 at 11:45 PM, Carsten Saager <csaager [at] gmail [dot] com> wrote:
> Cool, but entirely incompatible with coding standards that tell you to put
> any logic into the body of the loop.
>
> You fired from the Java team!
>
> Lucky Bastard ...
>
> -Carsten
>
> On Thu, Mar 19, 2009 at 9:03 PM, Jorge Ortiz <jorge [dot] ortiz [at] gmail [dot] com> wrote:
>>
>> This is my best shot at recreating that in Scala. I'm assuming Scalax's IO
>> library, which is lazy.
>>
>> The "skip" conditions have to be turned into "keep" conditions, but that's
>> just a matter of applying logical NOT to them.
>>
>>   import scalax.data.Implicits._
>>   import scalax.io.Implicits._
>>
>>   case class LineTime(line: String, time: Float)
>>
>>   (for {
>>     l <- infile.toFile.lines
>>     val line = l.trim
>>     if (line != "" && !line.startsWith("#"))
>>
>>     val data = line.split(",").toList
>>     if data.length >= 3
>>
>>     val ac = data(2)
>>     if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND
>> "))
>>
>>     val time = data(1).toFloat * sec
>>     if (time >= startTime || data(0) != "TRK")
>>   } yield LineTime(line, time)).takeWhile(_.time <= endTime).map(_.line)
>>
>> Now, that last line is arguably a bit ugly. It'd be the only thing I'd
>> change if break/continue were made available for Scala collections. I might
>> make the code look like so:
>>
>>   for {
>>     l <- infile.toFile.lines
>>     val line = l.trim
>>     if (line != "" && !line.startsWith("#"))
>>
>>     val data = line.split(",").toList
>>     if data.length >= 3
>>
>>     val ac = data(2)
>>     if (!acpair.isDefined || acpair.contains(ac) || line.startsWith("WND
>> "))
>>
>>     val time = data(1).toFloat * sec
>>     if (time >= startTime || data(0) != "TRK")
>>     val _ = if (time > endTime) break
>>   } yield line
>>
>> --j
>>
>> On Thu, Mar 19, 2009 at 12:37 PM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com>
>> wrote:
>>>
>>> Detering Dirk wrote:
>>> > I would be really, really interested in seeing a simplified
>>> > (but not oversimplified!) fully functional prototype version
>>> > of this usecase written in your style, and than let us
>>> > (well, not me, but the experts ;) ) show how that would be
>>> > solved in The Scala Way.
>>> >
>>> > It seems a sufficiently complex, but not too complex,
>>> > properly isolated problem for a showcase, and even coming
>>> > out of real world necessities.
>>> >
>>>
>>> OK, you asked for it, so here is a sample for you. This is a section from
>>> one of several Python scripts I use for processing the air traffic data
>>> files I mentioned. This is the simplest of those scripts, but it has the
>>> basics. Sorry, but this section of code by itself is not fully functional.
>>> First, here is the header comment just to give you a clue what it is doing:
>>>
>>> """
>>> This Python script by Russ Paielli extracts data for specified flights
>>> and a specified time window around an operational error from a TSAFE
>>> input data file (default: TSAFE-all.in). It puts the data into another
>>> smaller TSAFE input file (default: TSAFE.in). By default, the aircraft
>>> IDs of the conflict pair are specified in the input file ACpair.dat. If
>>> the --all option is used, all flights are extracted for the specified
>>> time period.
>>> """
>>>
>>> And here is the main looping portion of the script:
>>>
>>> count = 0
>>>
>>> for line in file(infile): # main loop
>>>
>>>     line = line.strip()
>>>     if not line or line.startswith("#"): print >> out, line; continue #
>>> skip blank line or comment
>>>
>>>     data = line.split()
>>>     if len(data) < 3: continue # bad data line
>>>     AC = data[2] # aircraft ID
>>>
>>>     if ACpair and AC not in ACpair and not line.startswith("WND "):
>>> continue
>>>
>>>     time = float(data[1]) * sec
>>>
>>>     if time < starttime and data[0] == "TRK": continue
>>>     if time > endtime: break
>>>
>>>     print >> out, line
>>>
>>>     count += 1
>>>
>>
>
>




--
Thanks,
-Vlad

Seth Tisue
Joined: 2008-12-16,
User offline. Last seen 34 weeks 3 days ago.
Re: [Fwd: Re: continue keyword]

Russ,

Here's another Scala version of your Python loop, completely different
from Jorge's.

I don't know scalax, so I didn't use it. I've done my best to make the
structure of the code follow the structure of the problem as I see it.

case class Entry(prefix:String,time:Double,id:String) {
def tooEarly = prefix == "TRK" && time < startTime
def tooLate = time > endTime
def ignorable = prefix != "WND" && !acPairs.isEmpty && !acPairs(id)
}
def parse(s:String):Option[Entry] =
s.split("\\s").filter(!_.isEmpty) match {
case Seq(prefix,time,id,_*) =>
Some(Entry(prefix,time.toDouble * sec,id))
case _ => None
}
def lines(path:String) =
Source.fromFile(path).getLines.map(_.stripLineEnd)
def isComment(s:String) = s.isEmpty || s.startsWith("#")
def process(path:String) {
for(line <- lines)
if(isComment(line)) println(line)
else for(entry <- parse(line)) {
if(entry.tooLate) return
if(!entry.tooEarly && !entry.ignorable)
println(line)
}
}

I have not run this; I hope there are no mistakes.

I imagine some of the functions would be usable elsewhere in the context
of a larger program.

I found "continue" easy to do without here, but I concede I wanted
"break". Score one for break or something like it; Jorge had trouble
too. I managed without break by using "return" instead. I could also
have used the same technique Jorge used involving takeWhile.

In my own code, if I found myself wanting or needing "break" or
"return", I would ask myself, "What did I do wrong that I ended up in
this position?" It's confusing to have a nonlocal exit deep within a
loop, so I would back up and try to refactor to make the problem
disappear. I can't do that for this example because I don't have the
context.

Seth Tisue
Joined: 2008-12-16,
User offline. Last seen 34 weeks 3 days ago.
Re: [Fwd: Re: continue keyword]

>>>>> "Vlad" == Vlad Patryshev writes:

Vlad> I think the trick is that if there is a good idea or solution,
Vlad> you learn it only once, but you save a lot on applying it many
Vlad> times afterwards. And even if learning looks hard before you do
Vlad> it... it does not look so hard when you are done.

Amen.

Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: [Fwd: Re: continue keyword]

We have a coding standard that says ( must be followed by a space, and
) preceded by a space. I fought long and hard (ok, I just mentioned
it in a meeting, and they agreed) to not have to have immutable
variables (vals in Scala, finals in Java) IN_ALL_UPPER_CASE.

I would like to write a coding standard that punishes the following
Java idioms, preferably with electric shock treatment through the
keyboard:

if (x == true)

_memberVariable

m_memberVariable

boolean ptInRect(Point p, Rectangle r) // this one is real code. No, really.
{
boolean ret = false;
if (r.contains(p))
{
ret = true;
}
return ret;
}

JButton getFooButton()
{
if (_fooBtn == null)
{
_fooBtn = new JButton("Foo");
_fooBtnInitialised = true;
}
return _fooBtn;
}

2009/3/19 Carsten Saager :
> If you happen to find my CV you'll come across the name of a company I
> worked for five years ago. Since then my stance on coding standards is to
> ignore them and stay away from groups that define them.
>
> To be fair, these standards had been derived from C-coding standards to have
> C++ standards. Extrapolating this to Scala would be complete nonsense and
> Jorge's code is the perfect example why.
>
> I also have some Java coding standards on my disk that I happily ignore for
> several years now. To get an idea, think of the Sun standard with all non
> Java specifics replaced by something that originates in Pascal. Add
> deliberately the MS naming conventions to have a real disgusting taste.
>
> Someone told me that they have the convention that code is indented by 8 and
> all comments start at the first col. Sounds familiar?
>
> If it is already hard to adapt formal criteria for code, how hard (and
> slow)  will it be to change the thinking?
>
> -Carsten
>
>
> On Thu, Mar 19, 2009 at 11:51 PM, Chris Twiner
> wrote:
>>
>> wow that would be a crazy standard, the python code loops on logic
>> (for each line in file), for loops would be out as all three elements
>> of control are logic.  while(true) only??
>>
>> on a serious note have you actually seen a standard like this?  what
>> kind of examples do they give for good loops and for bad loops?
>>
>> On Thu, Mar 19, 2009 at 11:45 PM, Carsten Saager
>> wrote:
>> > Cool, but entirely incompatible with coding standards that tell you to
>> > put
>> > any logic into the body of the loop.
>> >
>> > You fired from the Java team!
>> >
>> > Lucky Bastard ...
>> >
>> > -Carsten
>> >
>> > On Thu, Mar 19, 2009 at 9:03 PM, Jorge Ortiz
>> > wrote:
>> >>
>> >> This is my best shot at recreating that in Scala. I'm assuming Scalax's
>> >> IO
>> >> library, which is lazy.
>> >>
>> >> The "skip" conditions have to be turned into "keep" conditions, but
>> >> that's
>> >> just a matter of applying logical NOT to them.
>> >>
>> >>   import scalax.data.Implicits._
>> >>   import scalax.io.Implicits._
>> >>
>> >>   case class LineTime(line: String, time: Float)
>> >>
>> >>   (for {
>> >>     l <- infile.toFile.lines
>> >>     val line = l.trim
>> >>     if (line != "" && !line.startsWith("#"))
>> >>
>> >>     val data = line.split(",").toList
>> >>     if data.length >= 3
>> >>
>> >>     val ac = data(2)
>> >>     if (!acpair.isDefined || acpair.contains(ac) ||
>> >> line.startsWith("WND
>> >> "))
>> >>
>> >>     val time = data(1).toFloat * sec
>> >>     if (time >= startTime || data(0) != "TRK")
>> >>   } yield LineTime(line, time)).takeWhile(_.time <=
>> >> endTime).map(_.line)
>> >>
>> >> Now, that last line is arguably a bit ugly. It'd be the only thing I'd
>> >> change if break/continue were made available for Scala collections. I
>> >> might
>> >> make the code look like so:
>> >>
>> >>   for {
>> >>     l <- infile.toFile.lines
>> >>     val line = l.trim
>> >>     if (line != "" && !line.startsWith("#"))
>> >>
>> >>     val data = line.split(",").toList
>> >>     if data.length >= 3
>> >>
>> >>     val ac = data(2)
>> >>     if (!acpair.isDefined || acpair.contains(ac) ||
>> >> line.startsWith("WND
>> >> "))
>> >>
>> >>     val time = data(1).toFloat * sec
>> >>     if (time >= startTime || data(0) != "TRK")
>> >>     val _ = if (time > endTime) break
>> >>   } yield line
>> >>
>> >> --j
>> >>
>> >> On Thu, Mar 19, 2009 at 12:37 PM, Russ Paielli
>> >> wrote:
>> >>>
>> >>> Detering Dirk wrote:
>> >>> > I would be really, really interested in seeing a simplified
>> >>> > (but not oversimplified!) fully functional prototype version
>> >>> > of this usecase written in your style, and than let us
>> >>> > (well, not me, but the experts ;) ) show how that would be
>> >>> > solved in The Scala Way.
>> >>> >
>> >>> > It seems a sufficiently complex, but not too complex,
>> >>> > properly isolated problem for a showcase, and even coming
>> >>> > out of real world necessities.
>> >>> >
>> >>>
>> >>> OK, you asked for it, so here is a sample for you. This is a section
>> >>> from
>> >>> one of several Python scripts I use for processing the air traffic
>> >>> data
>> >>> files I mentioned. This is the simplest of those scripts, but it has
>> >>> the
>> >>> basics. Sorry, but this section of code by itself is not fully
>> >>> functional.
>> >>> First, here is the header comment just to give you a clue what it is
>> >>> doing:
>> >>>
>> >>> """
>> >>> This Python script by Russ Paielli extracts data for specified flights
>> >>> and a specified time window around an operational error from a TSAFE
>> >>> input data file (default: TSAFE-all.in). It puts the data into another
>> >>> smaller TSAFE input file (default: TSAFE.in). By default, the aircraft
>> >>> IDs of the conflict pair are specified in the input file ACpair.dat.
>> >>> If
>> >>> the --all option is used, all flights are extracted for the specified
>> >>> time period.
>> >>> """
>> >>>
>> >>> And here is the main looping portion of the script:
>> >>>
>> >>> count = 0
>> >>>
>> >>> for line in file(infile): # main loop
>> >>>
>> >>>     line = line.strip()
>> >>>     if not line or line.startswith("#"): print >> out, line; continue
>> >>> #
>> >>> skip blank line or comment
>> >>>
>> >>>     data = line.split()
>> >>>     if len(data) < 3: continue # bad data line
>> >>>     AC = data[2] # aircraft ID
>> >>>
>> >>>     if ACpair and AC not in ACpair and not line.startswith("WND "):
>> >>> continue
>> >>>
>> >>>     time = float(data[1]) * sec
>> >>>
>> >>>     if time < starttime and data[0] == "TRK": continue
>> >>>     if time > endtime: break
>> >>>
>> >>>     print >> out, line
>> >>>
>> >>>     count += 1
>> >>>
>> >>
>> >
>> >
>
>

Chris Twiner
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

This is great, I love stuff like this, trying to figure out what logic
lay behind decisions like these. I particularly liked Carstens pascal
driven standards, how do we simulate begin and end :-) I also love
the idea of hungarian notation in java land, should you use ptr or
lptr, good thing you can't do type aliases in java.

On Fri, Mar 20, 2009 at 10:34 AM, Ricky Clarkson
wrote:
> We have a coding standard that says ( must be followed by a space, and
> ) preceded by a space.  I fought long and hard (ok, I just mentioned
> it in a meeting, and they agreed) to not have to have immutable
> variables (vals in Scala, finals in Java) IN_ALL_UPPER_CASE.

I actually kind of like that for actual constants (ie. used throughout
the code) but would never dream of using it for a final private class
variable. I picked up the habit from working with non IDE's. Can't
say I've done java that way for over 5 years though, syntax
highlighting and nice names kinda make that dissapear.

> I would like to write a coding standard that punishes the following
> Java idioms, preferably with electric shock treatment through the
> keyboard:
>
> if (x == true)

I actually worked in a place where

if (true == x)

was littered throughout the code in C/C++ because the developers
wanted to stop !ptr tests for assignment and make boolean ones
explicit. I guess they never bothered to look at the type or use a
nice name.

> _memberVariable

guilty of doing this. I avoid it like the plauge but found my self
using it just yesterday as it was a private variable and I really
liked the name for a public function.

> m_memberVariable

Its possible that the _ just wasn't enough for some teams :-)

> boolean ptInRect(Point p, Rectangle r) // this one is real code.  No, really.
> {
>    boolean ret = false;
>    if (r.contains(p))
>    {
>        ret = true;
>    }
>    return ret;
> }

That is just priceless, truly a great way to start the day. I have
actually had developers complain about using logic in the return
statement though, although in this case even that is crazy.

> JButton getFooButton()
> {
>    if (_fooBtn == null)
>    {
>        _fooBtn = new JButton("Foo");
>        _fooBtnInitialised = true;
>    }
>    return _fooBtn;
> }

the above one might have had extra "functionality" planned at one
stage, but this one I just don't get though. Is it also real code?
Did the notion of the button having been initialised outlive the use
of the button?

I would also like to outlaw:

this.variableName

when used as the default (i.e. no actual name / scope collisions).

Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: [Fwd: Re: continue keyword]

>> if (x == true)
>
> I actually worked in a place where
>
> if (true == x)
>
> was littered throughout the code in C/C++ because the developers
> wanted to stop !ptr tests for assignment and make boolean ones
> explicit.  I guess they never bothered to look at the type or use a
> nice name.

Our C code has a lot of: x = x; y = y;. After seeing it a few times I
realised it wasn't an accident, then I stumbled across the comment //
to prevent warnings about unused variables

>
>> _memberVariable
>
> guilty of doing this.  I avoid it like the plauge but found my self
> using it just yesterday as it was a private variable and I really
> liked the name for a public function.

In Scala perhaps it's excusable as you can't use the same name for
both. In Java you can, so do. In C#, public methods tend to be
NamedLikeThis, so you can just do namedLikeThis for private stuff.

>> boolean ptInRect(Point p, Rectangle r) // this one is real code.  No, really.
>> {
>>    boolean ret = false;
>>    if (r.contains(p))
>>    {
>>        ret = true;
>>    }
>>    return ret;
>> }
>
> That is just priceless, truly a great way to start the day.  I have
> actually had developers complain about using logic in the return
> statement though, although in this case even that is crazy.
>
>> JButton getFooButton()
>> {
>>    if (_fooBtn == null)
>>    {
>>        _fooBtn = new JButton("Foo");
>>        _fooBtnInitialised = true;
>>    }
>>    return _fooBtn;
>> }
>
> the above one might have had extra "functionality" planned at one
> stage, but this one I just don't get though.  Is it also real code?

It is real code, except I added the _fooBtnInitialised bit for effect.

> I would also like to outlaw:
>
> this.variableName
>
> when used as the default (i.e. no actual name / scope collisions).
>

I think this one might actually help beginner Java programmers, who
regularly get static and non-static mixed up.
Kudos for Scala for not having static.

Chris Twiner
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

On Fri, Mar 20, 2009 at 12:23 PM, Ricky Clarkson
wrote:
>>> if (x == true)
> Our C code has a lot of: x = x; y = y;.  After seeing it a few times I
> realised it wasn't an accident, then I stumbled across the comment //
> to prevent warnings about unused variables

ingenious

>>> JButton getFooButton()
>>> {
>>>    if (_fooBtn == null)
>>>    {
>>>        _fooBtn = new JButton("Foo");
>>>        _fooBtnInitialised = true;
>>>    }
>>>    return _fooBtn;
>>> }
>>
>> the above one might have had extra "functionality" planned at one
>> stage, but this one I just don't get though.  Is it also real code?
>
> It is real code, except I added the _fooBtnInitialised bit for effect.

It does add an extra hint of terror.

>> I would also like to outlaw:
>>
>> this.variableName
>>
>> when used as the default (i.e. no actual name / scope collisions).
>>
>
> I think this one might actually help beginner Java programmers, who
> regularly get static and non-static mixed up.
> Kudos for Scala for not having static.
>

Never thought about that, primarly I guess as I came from C++. Is
this (the static thing) a common problem with beginners? I've not
seen any coworkers who had it.

Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: [Fwd: Re: continue keyword]

I found it to be the case when teaching Java programmers, until I
started presenting static differently (basically, instructing them not
to have static and non-static things in the same class unless they
knew what they were doing).

I still see it today on ##java on freenode IRC.

2009/3/20 Chris Twiner :
> On Fri, Mar 20, 2009 at 12:23 PM, Ricky Clarkson
> wrote:
>>>> if (x == true)
>> Our C code has a lot of: x = x; y = y;.  After seeing it a few times I
>> realised it wasn't an accident, then I stumbled across the comment //
>> to prevent warnings about unused variables
>
> ingenious
>
>>>> JButton getFooButton()
>>>> {
>>>>    if (_fooBtn == null)
>>>>    {
>>>>        _fooBtn = new JButton("Foo");
>>>>        _fooBtnInitialised = true;
>>>>    }
>>>>    return _fooBtn;
>>>> }
>>>
>>> the above one might have had extra "functionality" planned at one
>>> stage, but this one I just don't get though.  Is it also real code?
>>
>> It is real code, except I added the _fooBtnInitialised bit for effect.
>
> It does add an extra hint of terror.
>
>>> I would also like to outlaw:
>>>
>>> this.variableName
>>>
>>> when used as the default (i.e. no actual name / scope collisions).
>>>
>>
>> I think this one might actually help beginner Java programmers, who
>> regularly get static and non-static mixed up.
>> Kudos for Scala for not having static.
>>
>
> Never thought about that, primarly I guess as I came from C++.  Is
> this (the static thing) a common problem with beginners?  I've not
> seen any coworkers who had it.
>

Joel Neely
Joined: 2009-02-28,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

I think it was Joel Spolsky that I heard make the claim that bizarre
"standards" come from someone being bitten by a stupid mistake, and
making a local rule (sometimes equally stupid) to prevent that one
thing, then having the rule long outlive the original context (and
sometimes the original rule-maker).

Prime example: I recall observing a development team that was coding
Java, but whose technical lead mandated coding practices that had
obviously originated in an effort to prevent easily avoidable errors
in C.

On Fri, Mar 20, 2009 at 6:00 AM, Chris Twiner wrote:
> ...  I have
> actually had developers complain about using logic in the return
> statement though, although in this case even that is crazy.

You mean that they objected to using boolean expressions as
first-class values? I've encountered that a few times myself; it
seemed always to be from people with extremely narrow backgrounds.

-jn-

Chris Twiner
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

On Fri, Mar 20, 2009 at 1:18 PM, Joel Neely wrote:
>
> On Fri, Mar 20, 2009 at 6:00 AM, Chris Twiner wrote:
>> ...  I have
>> actually had developers complain about using logic in the return
>> statement though, although in this case even that is crazy.
>
> You mean that they objected to using boolean expressions as
> first-class values? I've encountered that a few times myself; it
> seemed always to be from people with extremely narrow backgrounds.
>

exactly, usually the reasons where along the lines of "make it more
explicit" because return !( condition && function()) wasn't that easy
to digest for them.

I guess that it tends in the direction of foldl(0)(_+_), for some its
obvious but for others its just a rude mess of symbols. You just have
to find the balance of expressiveness with your team mates. I don't
think it has much to do with ability either, really, as you suggest,
just different backgrounds and experience.

I'd hate a standard that forced Haskell users not to use the do
notation for dealing with monads for example, but I'm sure others
would be more than comfortable with it.

Robert Kosara
Joined: 2008-12-18,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]
On Fri, Mar 20, 2009 at 5:34 AM, Ricky Clarkson <ricky [dot] clarkson [at] gmail [dot] com> wrote:
JButton getFooButton()
{
   if (_fooBtn == null)
   {
       _fooBtn = new JButton("Foo");
       _fooBtnInitialised = true;
   }
   return _fooBtn;
}

Well except for that _fooBtnInitialised variable, this is a common way of building GUIs, either by hand or as the code generated by GUI builders. I got introduced to this many years ago as "lazy initialization," and I frankly don't see what's wrong with it. The idea is that you will need to refer to the button later, so you store a reference. There is a side effect, but the _fooBtn is private, so from the outside, you can't tell wether the button is recreated or not. Maybe it should be called makeFooButton, but other than that - what's wrong with this?
Martin S. Weber
Joined: 2008-12-23,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

Quoting Ricky Clarkson :

> (...)
> if (x == true)
> (...)

if (x == null)
if (x != null)

:(

Chris Twiner
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

On Fri, Mar 20, 2009 at 1:45 PM, Robert Kosara wrote:
> On Fri, Mar 20, 2009 at 5:34 AM, Ricky Clarkson
> wrote:
>>
>> JButton getFooButton()
>> {
>>    if (_fooBtn == null)
>>    {
>>        _fooBtn = new JButton("Foo");
>>        _fooBtnInitialised = true;
>>    }
>>    return _fooBtn;
>> }
>
> Well except for that _fooBtnInitialised variable, this is a common way of
> building GUIs, either by hand or as the code generated by GUI builders. I
> got introduced to this many years ago as "lazy initialization," and I
> frankly don't see what's wrong with it. The idea is that you will need to
> refer to the button later, so you store a reference. There is a side effect,
> but the _fooBtn is private, so from the outside, you can't tell wether the
> button is recreated or not. Maybe it should be called makeFooButton, but
> other than that - what's wrong with this?

Does the gui have an optionality regarding the button? Is it required
only in some particular use case, and not always present (as opposed
to being present and disabled). If its not always present I can
understand lazily creating it. If it is always present why not just
create it and be done with it :

in primary constructor (or init function or in line etc):

_fooBtn = new JButton("Foo");

protected JButton getFooButton() { return _fooBtn; } // I can't
really see a case for public access to a button but I'm sure there are
some.

lazy inits have their place but I don't see this as being one.

Robert Kosara
Joined: 2008-12-18,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

On Fri, Mar 20, 2009 at 8:57 AM, Chris Twiner <chris [dot] twiner [at] gmail [dot] com> wrote:
Does the gui have an optionality regarding the button?  Is it required only in some particular use case, and not always present (as opposed
to being present and disabled).  If its not always present I can
understand lazily creating it.  If it is always present why not just
create it and be done with it

True, this makes little sense for a single button. But it's used for whole panels or windows, where you might not show all of them, or not all at once, so they only get created as needed. That saves memory, and during development, it also saves grief from having to comment in or out different parts of the constructors before deciding what the final GUI will be. 
Chris Twiner
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

On Fri, Mar 20, 2009 at 2:23 PM, Robert Kosara wrote:
>
> On Fri, Mar 20, 2009 at 8:57 AM, Chris Twiner
> wrote:
>>
>> Does the gui have an optionality regarding the button?  Is it required
>> only in some particular use case, and not always present (as opposed
>> to being present and disabled).  If its not always present I can
>> understand lazily creating it.  If it is always present why not just
>> create it and be done with it
>
> True, this makes little sense for a single button. But it's used for whole
> panels or windows, where you might not show all of them, or not all at once,
> so they only get created as needed. That saves memory, and during
> development, it also saves grief from having to comment in or out different
> parts of the constructors before deciding what the final GUI will be.
>

I can see where that might make some sense but I think its also
indicative of a slightly wierd design. Surely if the panels or
windows were optional the data they showed and actions taken would
also be, that hints towards seperate classes that wrap that behaviour,
that simply don't get created. But we don't always have the option of
changing the designs we work with.

Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: [Fwd: Re: continue keyword]

The problem with it is that it makes temporal coupling harder to see,
and it's not threadsafe.

JButton _fooBtn;

Looking at that, and only that, I have to assume that _fooBtn might be
written to n times.

So I right click and find references to it, looking for assigns. I
find the lazy initialiser. The lazy initialiser might be 'simple'
like the one I already showed, or it might do something like: _fooBtn
= new JButton(getSomethingElse().getText());

So I follow the flow into getSomethingElse(), and getSomethingElse()
returns somethingElse (no lazy initialisation). I look at
somethingElse's declaration and it's a) final SomethingElse
somethingElse = new.., or b) unassigned.

Assuming b), I look for assigns to somethingElse, and I find that
somethingElse is 'injected' via a public setter.

All this navigating has showed me that _fooBtn depends on
somethingElse, that it depends on a value not available at
construction. The naming isn't pretty, but this would be a better
structure:

class Bar {
private var somethingElsePlusDependents:
Option[SomethingElsePlusDependents] = None
def somethingElse_=(s: SomethingElse) =
somethingElsePlusDependents = Some(SomethingElsePlusDependents(s))
def fooButton = somethingElsePlusDependents match {
case Some(s) => s.fooButton
case None => throw null
}
}

Note that this also fixes a bug in the original version;
setSomethingElse called twice would have caused _fooBtn's text to be
out of date.

It helps if what can be final (or val) is final, then you can see the
parts of the object that are defined at instantiation - the topology
of the class, if you like.

This observation is based on real code, a 2100 line file, with 40
lazily initialised fields, 20 of which could trivially have been
finals, and 10 of the remaining fields less trivially made into
finals. The file now has 1500 lines, and fewer known bugs.

2009/3/20 Robert Kosara :
> On Fri, Mar 20, 2009 at 5:34 AM, Ricky Clarkson
> wrote:
>>
>> JButton getFooButton()
>> {
>>    if (_fooBtn == null)
>>    {
>>        _fooBtn = new JButton("Foo");
>>        _fooBtnInitialised = true;
>>    }
>>    return _fooBtn;
>> }
>
> Well except for that _fooBtnInitialised variable, this is a common way of
> building GUIs, either by hand or as the code generated by GUI builders. I
> got introduced to this many years ago as "lazy initialization," and I
> frankly don't see what's wrong with it. The idea is that you will need to
> refer to the button later, so you store a reference. There is a side effect,
> but the _fooBtn is private, so from the outside, you can't tell wether the
> button is recreated or not. Maybe it should be called makeFooButton, but
> other than that - what's wrong with this?
>

Detering Dirk
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
RE: [Fwd: Re: continue keyword]

Hi Russ,

thanks for the example.
I had not much time to look into it now (far too busy :-( )
to think about a Scala-ish solution myself (well, the
experienced people already answered ...), and the thread
already overtook me.

What I noticed at a first glance is, that even this
imperative version does in no way *need* a 'continue',
as each is only a syntactic shortcut for an 'else'
with further indentation, or the indentation per se.

Well some conditions had to be switched ... but I
prefer anyway seeing when things happen and
not when they don't.

It was hard for me to grok the 'if' with this Apair
stuff, and when I got it, that was the line-type that
was *not* processed. So what lines *are* processed?

You may find the indentation annoying, but for me
your orignal version had the flaw of everything-at-one-level
which made it hard for me to find all the exit-points
of the process. I indeed found all three 'continue's only
when I started to replace them.

Sorry, but my short Python time was very long ago,
so I may indeed miss something here.

count = 0

for line in file(infile): # main loop

line = line.strip()
if not line or line.startswith("#"):
print >> out, line;

else:

data = line.split()
if len(data) >= 3: # good data line ;-)
AC = data[2] # aircraft ID

if not ACpair or AC in ACpair or line.startswith("WND "):
time = float(data[1]) * sec

if time > starttime or data[0] == "TRK":
if time > endtime: break

print >> out, line

count += 1

The break could perhaps be replaced by a flag which is tested
as part of the loop condition, if the line reading would not
be main action of the loop, don't know.
I have the impression that better separation into single
functions/methods with an adequate point of 'return' will do
without such flag.

I will think about that...

KR
Det

> -----Original Message-----
> From: Russ Paielli [mailto:russ [dot] paielli [at] gmail [dot] com]
> Sent: Thursday, March 19, 2009 8:37 PM
> To: scala-user
> Subject: Re: [Fwd: Re: [scala-user] continue keyword]
>
> Detering Dirk wrote:
> > I would be really, really interested in seeing a simplified
> > (but not oversimplified!) fully functional prototype version
> > of this usecase written in your style, and than let us
> > (well, not me, but the experts ;) ) show how that would be
> > solved in The Scala Way.
> >
> > It seems a sufficiently complex, but not too complex,
> > properly isolated problem for a showcase, and even coming
> > out of real world necessities.
> >
>
> OK, you asked for it, so here is a sample for you. This is a
> section from one of several Python scripts I use for
> processing the air traffic data files I mentioned. This is
> the simplest of those scripts, but it has the basics. Sorry,
> but this section of code by itself is not fully functional.
> First, here is the header comment just to give you a clue
> what it is doing:
>
> """
> This Python script by Russ Paielli extracts data for specified flights
> and a specified time window around an operational error from a TSAFE
> input data file (default: TSAFE-all.in). It puts the data into another
> smaller TSAFE input file (default: TSAFE.in). By default, the aircraft
> IDs of the conflict pair are specified in the input file
> ACpair.dat. If
> the --all option is used, all flights are extracted for the specified
> time period.
> """
>
> And here is the main looping portion of the script:
>
> count = 0
>
> for line in file(infile): # main loop
>
> line = line.strip()
> if not line or line.startswith("#"): print >> out, line;
> continue # skip blank line or comment
>
> data = line.split()
> if len(data) < 3: continue # bad data line
> AC = data[2] # aircraft ID
>
> if ACpair and AC not in ACpair and not
> line.startswith("WND "): continue
>
> time = float(data[1]) * sec
>
> if time < starttime and data[0] == "TRK": continue
> if time > endtime: break
>
> print >> out, line
>
> count += 1
>
>
>

Detering Dirk
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
RE: [Fwd: Re: continue keyword]

> boolean ptInRect(Point p, Rectangle r) // real code
> {
> boolean ret = false;
> if (r.contains(p))
> {
> ret = true;
> }
> return ret;
> }

ARRRGGHH.

Do you know how much of this kind I refactored in the
last two weeks??

We are working with a code generator which has user sections
in generated method frames like this:

boolean ptInRect(Point p, Rectangle r) // real code
{
boolean ret = false;
// user code start

if (someCheck) {
ret = true;
}

// user code end
return ret;
}

That is ok so far, but people often forget that this
structure makes no sense in completely hand written code.
"Thinking in patterns" .... ;-) .

KR
Det

Eric Schwarzenbach
Joined: 2009-02-06,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

Ricky Clarkson wrote:
> boolean ptInRect(Point p, Rectangle r) // this one is real code. No, really.
> {
> boolean ret = false;
> if (r.contains(p))
> {
> ret = true;
> }
> return ret;
> }
>
> JButton getFooButton()
> {
> if (_fooBtn == null)
> {
> _fooBtn = new JButton("Foo");
> _fooBtnInitialised = true;
> }
> return _fooBtn;
> }
>
These sorts of things can come about simply from refactoring. For
example someone might have moved that bit of logic from class that
ptInRect was part of to Rectangle, and left that method temporarily so
as not to break some other code (perhaps code out of the programmers
control, on a different release schedule, etc.). The intention to remove
it later may have been a casualty of tight schedules, turn-over, or
simple honest human error. getFooButton could have contained a lot more
logic at one point and atrophied away.

Any lengthy and long-lived codebase tends to develop silly bits. I'm not
saying they shouldn't be fixed, but they often happen honestly.

Russ P.
Joined: 2009-01-31,
User offline. Last seen 1 year 26 weeks ago.
Re: [Fwd: Re: continue keyword]
Hi Seth,

Your Scala solution without break and continue is interesting. On the one hand, it shows your knowledge of Scala -- which certainly exceeds mine. On the other hand, I think it shows that the problem is substantially harder to solve without break and continue. You needed an extra class and an extra couple of functions to do what I did in Python with a relatively simple loop. And I think my Python version is simpler to read and understand too.

Scala is a very nice language. My hat is off to its designers, who understand far more than I ever will about language design. Nevertheless, this thread has reinforced my initial reaction that the lack of continue and break are a problem. And the I think the quasi-ideological opposition to them in the Scala community is misplaced. Had Martin Odersky not recently proposed adding them as library abstractions, I bet I'd be taking major flak here. His proposal certainly eases the problem for me because I can now add continue and break in my own code without waiting for anyone else to approve and implement them. The only problem at this point is aesthetic: I need to clutter my code slightly with awkward words like "breakable" and "continuable." If I could just figure out how to abstract

breakable { for(...) continuable {

and call it "For" or something like that, the problem would be completely solved for me.

This is not to dismiss the other proposals by David McIver. His ideas are just too advanced for me to understand at this point.

Regards,
Russ P.


On Thu, Mar 19, 2009 at 8:27 PM, Seth Tisue <seth [at] tisue [dot] net> wrote:

Russ,

Here's another Scala version of your Python loop, completely different
from Jorge's.

I don't know scalax, so I didn't use it.  I've done my best to make the
structure of the code follow the structure of the problem as I see it.

case class Entry(prefix:String,time:Double,id:String) {
 def tooEarly = prefix == "TRK" && time < startTime
 def tooLate = time > endTime
 def ignorable = prefix != "WND" && !acPairs.isEmpty && !acPairs(id)
}
def parse(s:String):Option[Entry] =
 s.split("\\s").filter(!_.isEmpty) match {
   case Seq(prefix,time,id,_*) =>
     Some(Entry(prefix,time.toDouble * sec,id))
   case _ => None
 }
def lines(path:String) =
 Source.fromFile(path).getLines.map(_.stripLineEnd)
def isComment(s:String) = s.isEmpty || s.startsWith("#")
def process(path:String) {
 for(line <- lines)
   if(isComment(line)) println(line)
   else for(entry <- parse(line)) {
     if(entry.tooLate) return
     if(!entry.tooEarly && !entry.ignorable)
       println(line)
   }
}

I have not run this; I hope there are no mistakes.

I imagine some of the functions would be usable elsewhere in the context
of a larger program.

I found "continue" easy to do without here, but I concede I wanted
"break".  Score one for break or something like it; Jorge had trouble
too.  I managed without break by using "return" instead.  I could also
have used the same technique Jorge used involving takeWhile.

In my own code, if I found myself wanting or needing "break" or
"return", I would ask myself, "What did I do wrong that I ended up in
this position?"  It's confusing to have a nonlocal exit deep within a
loop, so I would back up and try to refactor to make the problem
disappear.  I can't do that for this example because I don't have the
context.

--
Seth Tisue / http://tisue.net
lead developer, NetLogo: http://ccl.northwestern.edu/netlogo/



--
http://RussP.us
DRMacIver
Joined: 2008-09-02,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

2009/3/20 Russ Paielli :
> Hi Seth,
>
> Your Scala solution without break and continue is interesting. On the one
> hand, it shows your knowledge of Scala -- which certainly exceeds mine. On
> the other hand, I think it shows that the problem is substantially harder to
> solve without break and continue. You needed an extra class and an extra
> couple of functions to do what I did in Python with a relatively simple
> loop. And I think my Python version is simpler to read and understand too.
>
> Scala is a very nice language. My hat is off to its designers, who
> understand far more than I ever will about language design. Nevertheless,
> this thread has reinforced my initial reaction that the lack of continue and
> break are a problem. And the I think the quasi-ideological opposition to
> them in the Scala community is misplaced. Had Martin Odersky not recently
> proposed adding them as library abstractions, I bet I'd be taking major flak
> here. His proposal certainly eases the problem for me because I can now add
> continue and break in my own code without waiting for anyone else to approve
> and implement them. The only problem at this point is aesthetic: I need to
> clutter my code slightly with awkward words like "breakable" and
> "continuable." If I could just figure out how to abstract
>
> breakable { for(...) continuable {
>
> and call it "For" or something like that, the problem would be completely
> solved for me.

http://gist.github.com/79133

Usage:

loop(test){
do stuff in here. break and continue work as you'd expect.
}

foreach(items){ item =>
do stuff with item in here. break and continue again work as you'd expect.
}

Ricky Clarkson
Joined: 2008-12-19,
User offline. Last seen 3 years 2 weeks ago.
Re: [Fwd: Re: continue keyword]

But David, your ideas are too advanced. If you are not careful, there
will be exploded minds on the driveway.

2009/3/20 David MacIver :
> 2009/3/20 Russ Paielli :
>> Hi Seth,
>>
>> Your Scala solution without break and continue is interesting. On the one
>> hand, it shows your knowledge of Scala -- which certainly exceeds mine. On
>> the other hand, I think it shows that the problem is substantially harder to
>> solve without break and continue. You needed an extra class and an extra
>> couple of functions to do what I did in Python with a relatively simple
>> loop. And I think my Python version is simpler to read and understand too.
>>
>> Scala is a very nice language. My hat is off to its designers, who
>> understand far more than I ever will about language design. Nevertheless,
>> this thread has reinforced my initial reaction that the lack of continue and
>> break are a problem. And the I think the quasi-ideological opposition to
>> them in the Scala community is misplaced. Had Martin Odersky not recently
>> proposed adding them as library abstractions, I bet I'd be taking major flak
>> here. His proposal certainly eases the problem for me because I can now add
>> continue and break in my own code without waiting for anyone else to approve
>> and implement them. The only problem at this point is aesthetic: I need to
>> clutter my code slightly with awkward words like "breakable" and
>> "continuable." If I could just figure out how to abstract
>>
>> breakable { for(...) continuable {
>>
>> and call it "For" or something like that, the problem would be completely
>> solved for me.
>
> http://gist.github.com/79133
>
> Usage:
>
> loop(test){
>   do stuff in here. break and continue work as you'd expect.
> }
>
> foreach(items){ item =>
>  do stuff with item in here. break and continue again work as you'd expect.
> }
>

Robert Macomber
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

On 2009-03-20, David MacIver wrote:
> http://gist.github.com/79133
>
> Usage:
>
> loop(test){
> do stuff in here. break and continue work as you'd expect.
> }
>
> foreach(items){ item =>
> do stuff with item in here. break and continue again work as you'd expect.
> }

But they don't. I'd expect break and continue to be lexically scoped,
but those "break" and "continue" are dynamically scoped. This is a
general problem when passing around functions that may throw
exceptions as first-class objects; I'm not at all sure that exceptions
and higher-order programming are features that coexist easily in the
same language.

DRMacIver
Joined: 2008-09-02,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: [Fwd: Re: continue keyword]

2009/3/20 Robert Macomber :
> On 2009-03-20, David MacIver wrote:
>> http://gist.github.com/79133
>>
>> Usage:
>>
>> loop(test){
>>    do stuff in here. break and continue work as you'd expect.
>> }
>>
>> foreach(items){ item =>
>>   do stuff with item in here. break and continue again work as you'd expect.
>> }
>
> But they don't.  I'd expect break and continue to be lexically scoped,
> but those "break" and "continue" are dynamically scoped.  This is a
> general problem when passing around functions that may throw
> exceptions as first-class objects;

breaks and continues (without labels) always break from the nearest
enclosing thing that applies. The only difference making them
lexically versus dynamically scoped has is that this way they apply to
a bunch more things and gain a lot of flexibility. The programs that
are valid in this version are a strict superset of those that are
valid in the normal version, and where both are valid they mean the
same thing.

Or, in other words: This is a feature, not a bug.

> I'm not at all sure that exceptions
> and higher-order programming are features that coexist easily in the
> same language.

And yet there's a long history of the two coexisting just fine showing
otherwise.

Brett Knights
Joined: 2009-01-18,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

On Thu, Mar 19, 2009 at 1:03 PM, Jorge Ortiz > wrote:
>
> This is my best shot at recreating that in Scala. I'm assuming
> Scalax's IO library, which is lazy.
>
> The "skip" conditions have to be turned into "keep" conditions,
> but that's just a matter of applying logical NOT to them.
>
> import scalax.data.Implicits._
> import scalax.io.Implicits._
>
> case class LineTime(line: String, time: Float)
>
> (for {
> l <- infile.toFile.lines
> val line = l.trim
> if (line != "" && !line.startsWith("#"))
>
> val data = line.split(",").toList
> if data.length >= 3
>
> val ac = data(2)
> if (!acpair.isDefined || acpair.contains(ac) ||
> line.startsWith("WND "))
>
> val time = data(1).toFloat * sec
> if (time >= startTime || data(0) != "TRK")
> } yield LineTime(line, time)).takeWhile(_.time <=
> endTime).map(_.line)
>
Doesn't this one still read all the lines?

A somewhat simpler to comprehend set up was suggested by this post:
http://creativekarma.com/ee.php/weblog/comments/the_scala_for_comprehens...
The following ignores all the parsing logic although it should be
obvious where it would go.
I don't know if the external "go" var is objectionable from an FP pov
but the control seems nice and clean.

object lineTaker{

def main(args: Array[String]) {

import scalax.io.Implicits._
import java.io.File

val infile = new File(args(0));

var go = true;
for { l <- infile.readLines.projection.takeWhile(l => go)}{
l.trim() match{ // match handles parallel cases so no need
for continue
case "ted" => go = false; // break handled in takeWhile
case x => println(x);
}
}
}
}

Christian Szegedy
Joined: 2009-02-08,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

For comprehensions for streams should yield streams (it is just
transformed into filters and flatMaps) and therefore takeWhile should
cause early termination even in the original code.

On 3/20/09, Brett Knights wrote:
>
> >
> Doesn't this one still read all the lines?
>
>

Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 3 days ago.
Re: [Fwd: Re: continue keyword]

Doesn't this one still read all the lines?
 
No. The 'lines' method returns a ManagedSequence[String], which is a lazy "collection". Evaluation (and thus, file access) will be delayed until it's needed. Because of the takeWhile condition, evaluation (and thus, file access) will terminate early. Thanks to lazy evaluation, it also processes the file in O(1) (constant) memory.

Your code, on the other hand, will not only read the entire file, it will put the entire file into memory (O(N)), as readLines returns a (strict) List[String]. Not only will your code read the entire file, it will throw OOMException for large files.

--j
Seth Tisue
Joined: 2008-12-16,
User offline. Last seen 34 weeks 3 days ago.
Re: [Fwd: Re: continue keyword]

>>>>> "Russ" == Russ Paielli writes:

Russ> Hi Seth, Your Scala solution without break and continue is
Russ> interesting. On the one hand, it shows your knowledge of Scala --
Russ> which certainly exceeds mine. On the other hand, I think it shows
Russ> that the problem is substantially harder to solve without break
Russ> and continue. You needed an extra class and an extra couple of
Russ> functions to do what I did in Python with a relatively simple
Russ> loop. And I think my Python version is simpler to read and
Russ> understand too.

Well, you can probably guess I'm going to disagree :-)

I believe my version is easier to understand, because you can understand
the overall structure simply by reading this one part:

for(line <- lines)
if(isComment(line)) println(line)
else for(entry <- parse(line)) {
if(entry.tooLate) return
if(!entry.tooEarly && !entry.ignorable)
println(line)
}

All the essentials are right there. The other definitions just supply
details.

In your version, there is no separation of concerns; everything is all
mixed together, so I have to wade through all of the low-level detail in
order to get even a basic understanding of the structure and purpose of
the loop. I have to figure out for myself what is structure and what is
detail. And I can't grasp the structure until I've located every
"break" and every "continue" and figured out how they all interrelate.
Doing that took me a long time; a much longer time than it takes to read
and understand my version above.

In relatively short programs, written and maintained by one person, the
difference may not matter much. You described your code as "not
critical production code", and I think that for that kind of code, your
approach is just fine. I often do it that way too when I'm writing
small, temporary programs. But that approach (writing long, complex
loops where separation of concerns is nonexistent) is not an approach to
programming that scales to programs where correctness is important, to
larger programs, to programs that are maintained by multiple people, or
to programs that will grow and change over time.

By the way, I don't actually have a strong feeling one way or the other
about whether "break" or "continue" should be in the language (or in the
standard library). I already conceded that this example is a pretty
good one for wanting "break". The real point I want to make is that if
you are routinely using "break" and "continue" in multiple places in
long, complex loops, you are probably writing code which is difficult
for other people to understand and nightmarish for other people to
maintain and modify. That's why I consider it relatively unimportant
whether or not Scala gets "break" and "continue".

Brett Knights
Joined: 2009-01-18,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

Jorge Ortiz wrote:
>
> Doesn't this one still read all the lines?
>
>
> No. The 'lines' method returns a ManagedSequence[String], which is a
> lazy "collection". Evaluation (and thus, file access) will be delayed
> until it's needed. Because of the takeWhile condition, evaluation (and
> thus, file access) will terminate early. Thanks to lazy evaluation, it
> also processes the file in O(1) (constant) memory.
>
> Your code, on the other hand, will not only read the entire file, it
> will put the entire file into memory (O(N)), as readLines returns a
> (strict) List[String]. Not only will your code read the entire file,
> it will throw OOMException for large files.
>
> --j
Actually I thought that I was using readLines from scalax that produces
a Seq[String]. Oh well. It also works just as well to use lines so the
following is revised:

import scalax.io.Implicits._
import java.io.File

val infile = new File(args(0));

var go = true;
for { l <- infile.lines.takeWhile(l => go)}{
l.trim() match{ // no need for continue
case "ted" => go = false; // break handled
case x => println(x);
}
}

but what I think you are saying is that your original for comprehension
is actually being pulled from only so long as the takeWhile returns
true. That's pretty cool if that is what's happening.

(for {l <- infile.toFile.lines
... guards etc
} yield LineTime(line, time)).takeWhile

Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 3 days ago.
Re: [Fwd: Re: continue keyword]
Yeah, it returns a Seq[String] which is backed by a List[String].

And yeah, the for-comprehension is just a sequence of calls to filter, map, and flatMap, which preserve the laziness of ManagedSequence.

And yes, your revised version works.

--j

On Fri, Mar 20, 2009 at 3:08 PM, Brett Knights <brett [at] knightsofthenet [dot] com> wrote:
Jorge Ortiz wrote:

   Doesn't this one still read all the lines?

 No. The 'lines' method returns a ManagedSequence[String], which is a lazy "collection". Evaluation (and thus, file access) will be delayed until it's needed. Because of the takeWhile condition, evaluation (and thus, file access) will terminate early. Thanks to lazy evaluation, it also processes the file in O(1) (constant) memory.

Your code, on the other hand, will not only read the entire file, it will put the entire file into memory (O(N)), as readLines returns a (strict) List[String]. Not only will your code read the entire file, it will throw OOMException for large files.

--j
Actually I thought that I was using readLines from scalax that produces a Seq[String]. Oh well. It also works just as well to use lines so the following is revised:


      import scalax.io.Implicits._
      import java.io.File

      val infile = new File(args(0));

      var go = true;
      for { l <- infile.lines.takeWhile(l => go)}{
          l.trim() match{ // no need for continue
                  case "ted" => go = false; // break handled
                  case x => println(x);
              }
      }

but what I think you are saying is that your original for comprehension is actually being pulled from only so long as the takeWhile returns true. That's pretty cool if that is what's happening.

(for {l <- infile.toFile.lines
... guards etc
    } yield LineTime(line, time)).takeWhile

Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 3 days ago.
Re: [Fwd: Re: continue keyword]
On further reflection, another way to write it (without takeWhile) would be:

  var go = true
  for (line <- infile.toFile.lines if go) {
    ...
  }

--j

--j

On Fri, Mar 20, 2009 at 3:19 PM, Jorge Ortiz <jorge [dot] ortiz [at] gmail [dot] com> wrote:
Yeah, it returns a Seq[String] which is backed by a List[String].

And yeah, the for-comprehension is just a sequence of calls to filter, map, and flatMap, which preserve the laziness of ManagedSequence.

And yes, your revised version works.

--j

On Fri, Mar 20, 2009 at 3:08 PM, Brett Knights <brett [at] knightsofthenet [dot] com> wrote:
Jorge Ortiz wrote:

   Doesn't this one still read all the lines?

 No. The 'lines' method returns a ManagedSequence[String], which is a lazy "collection". Evaluation (and thus, file access) will be delayed until it's needed. Because of the takeWhile condition, evaluation (and thus, file access) will terminate early. Thanks to lazy evaluation, it also processes the file in O(1) (constant) memory.

Your code, on the other hand, will not only read the entire file, it will put the entire file into memory (O(N)), as readLines returns a (strict) List[String]. Not only will your code read the entire file, it will throw OOMException for large files.

--j
Actually I thought that I was using readLines from scalax that produces a Seq[String]. Oh well. It also works just as well to use lines so the following is revised:


      import scalax.io.Implicits._
      import java.io.File

      val infile = new File(args(0));

      var go = true;
      for { l <- infile.lines.takeWhile(l => go)}{
          l.trim() match{ // no need for continue
                  case "ted" => go = false; // break handled
                  case x => println(x);
              }
      }

but what I think you are saying is that your original for comprehension is actually being pulled from only so long as the takeWhile returns true. That's pretty cool if that is what's happening.

(for {l <- infile.toFile.lines
... guards etc
    } yield LineTime(line, time)).takeWhile

Robert Macomber
Joined: 2009-03-20,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

On 2009-03-20, David MacIver wrote:
> 2009/3/20 Robert Macomber :
>> But they don't.  I'd expect break and continue to be lexically scoped,
>> but those "break" and "continue" are dynamically scoped.  This is a
>> general problem when passing around functions that may throw
>> exceptions as first-class objects;
>
> breaks and continues (without labels) always break from the nearest
> enclosing thing that applies. The only difference making them
> lexically versus dynamically scoped has is that this way they apply to
> a bunch more things and gain a lot of flexibility. The programs that
> are valid in this version are a strict superset of those that are
> valid in the normal version, and where both are valid they mean the
> same thing.

But they don't. Consider:

def silly {
loop(true) {
evenSillier {
break
}
}
}

def evenSillier(action : =>Unit) {
loop(true) {
action
break
}
println("Exiting evenSillier now")
}

If "break" is lexically scoped, calling silly is a no-op. If break is
dynamically scoped, it loops forever printing "Exiting evenSillier
now". The dynamic scoping exposes an implementation detail of the
second function.

>> I'm not at all sure that exceptions
>> and higher-order programming are features that coexist easily in the
>> same language.
>
> And yet there's a long history of the two coexisting just fine showing
> otherwise.

This is true. It doesn't stop me being nervous about it, for exactly
the reason given above -- a function can throw an exception that gets
unexpectedly handled by code that's using the same exception type for
a different purpose.

Brett Knights
Joined: 2009-01-18,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

Jorge Ortiz wrote:
> On further reflection, another way to write it (without takeWhile)
> would be:
>
> var go = true
> for (line <- infile.toFile.lines if go) {
> ...
> }
>
according to the article I cited that would produce the correct output
but would end up reading all the lines (and I assume discarding them --
no OOM at least) because the guard doesn't stop the generator so once go
has been set to true all the rest of the lines in the file will just be
read and skipped.

This has certainly been an educational thread.

DRMacIver
Joined: 2008-09-02,
User offline. Last seen 42 years 45 weeks ago.
Re: Re: [Fwd: Re: continue keyword]

2009/3/20 Robert Macomber :
> On 2009-03-20, David MacIver wrote:
>> 2009/3/20 Robert Macomber :
>>> But they don't.  I'd expect break and continue to be lexically scoped,
>>> but those "break" and "continue" are dynamically scoped.  This is a
>>> general problem when passing around functions that may throw
>>> exceptions as first-class objects;
>>
>> breaks and continues (without labels) always break from the nearest
>> enclosing thing that applies. The only difference making them
>> lexically versus dynamically scoped has is that this way they apply to
>> a bunch more things and gain a lot of flexibility. The programs that
>> are valid in this version are a strict superset of those that are
>> valid in the normal version, and where both are valid they mean the
>> same thing.
>
> But they don't.  Consider:
>
> def silly {
>  loop(true) {
>    evenSillier {
>      break
>    }
>  }
> }
>
> def evenSillier(action : =>Unit) {
>  loop(true) {
>    action
>    break
>  }
>  println("Exiting evenSillier now")
> }
>
> If "break" is lexically scoped, calling silly is a no-op.  If break is
> dynamically scoped, it loops forever printing "Exiting evenSillier
> now".  The dynamic scoping exposes an implementation detail of the
> second function.

Hm. On the one hand, you are correct. My mistake, sorry.

On the other hand, still seems like a feature to me. It's like saying:

while(true){
while(true){
break;
}
}

and being surprised that the inner break doesn't break out of the
enclosing loop. Doing things this way introduces a slightly larger
class of things which have semantically meaningful breaks. This does
however mean you have to be quite careful about documenting this
behaviour.

I agree this is a somewhat worrying example. I'll have a think about
it. At the very least it's a strong argument for including labelled
breaks:

labelledBreak{ label =>
while(true){
while(true){
break(label);
}
}
}

Not as pretty as it could be, but it works reasonably well.

>>> I'm not at all sure that exceptions
>>> and higher-order programming are features that coexist easily in the
>>> same language.
>>
>> And yet there's a long history of the two coexisting just fine showing
>> otherwise.
>
> This is true.  It doesn't stop me being nervous about it, for exactly
> the reason given above -- a function can throw an exception that gets
> unexpectedly handled by code that's using the same exception type for
> a different purpose.

It's always been just as important to indicate what exceptions you can
swallow as it is to indicate what exceptions you throw. Higher order
functions just make it a bit more so.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland