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

[Fwd: Re: continue keyword]

57 replies
Jorge Ortiz
Joined: 2008-12-16,
User offline. Last seen 29 weeks 3 days ago.
Re: [Fwd: Re: continue keyword]
Ahh, yes, you're correct. Every line will be read and discarded, but not processed.

--j

On Fri, Mar 20, 2009 at 3:36 PM, Brett Knights <brett [at] knightsofthenet [dot] com> wrote:
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.


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

Robert Macomber wrote:
>
> 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
Might not a solution to satisfy both imperative programmers and
functional purists, be to implement break and continue as language
keywords, and have the scala compiler generate code for continue and
break just as if you had written the equivalent using additional
if/else/end loop conditions instead of continue and break?

Eric

Russ P.
Joined: 2009-01-31,
User offline. Last seen 1 year 26 weeks ago.
Re: [Fwd: Re: continue keyword]
On Fri, Mar 20, 2009 at 2:39 PM, Seth Tisue <seth [at] tisue [dot] net> wrote:
>>>>> "Russ" == Russ Paielli <russ [dot] paielli [at] gmail [dot] com> 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.

Your version may indeed be more readable than mine. But your version uses an extra class and a few extra "helper" functions. So any improved readability in your version is due to the level of abstraction and is more or less independent of the fact that you eliminated "break" and "continue." I could improve the readability of my version too by using your helper functions and keeping "break" and "continue." I'll bet it would be as readable as yours.
 

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.

I agree, but as I said, I don't think the main issue here is "break" and "continue."

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".

Fair enough.

Russ P.
 

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> So any improved readability in your version is due to
Russ> the level of abstraction and is more or less independent of the
Russ> fact that you eliminated "break" and "continue." I could improve
Russ> the readability of my version too by using your helper functions
Russ> and keeping "break" and "continue." I'll bet it would be as
Russ> readable as yours.

Yes, I agree.

Compared to Java, Scala makes it far more convenient and pleasant to
clarify the structure of code by decomposing it into small functions and
classes. That's a major reason I'm much happier coding in Scala than
Java. I don't know about Scala vs. Python, because I don't know Python
well enough.

Russ P.
Joined: 2009-01-31,
User offline. Last seen 1 year 26 weeks ago.
Re: [Fwd: Re: continue keyword]
David MacIver's solution to the continue/break problem allows one to write

foreach(0 to 10){ i => ...}

That is very nice, but I was just wondering if it is possible to go a tiny step further and make it syntactically identical to "for", so one could write something like

For(i <- 0 to 10) { ...} // and have break and continue

Russ P.


On Fri, Mar 20, 2009 at 12:14 PM, David MacIver <david [dot] maciver [at] gmail [dot] com> wrote:
2009/3/20 Russ Paielli <russ [dot] paielli [at] gmail [dot] com>:

> 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.
}

Naftoli Gugenheim
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]
IIRC <- is considered a keyword.

On Mon, Mar 23, 2009 at 5:11 PM, Russ Paielli <russ [dot] paielli [at] gmail [dot] com> wrote:
David MacIver's solution to the continue/break problem allows one to write

foreach(0 to 10){ i => ...}

That is very nice, but I was just wondering if it is possible to go a tiny step further and make it syntactically identical to "for", so one could write something like

For(i <- 0 to 10) { ...} // and have break and continue

Russ P.


On Fri, Mar 20, 2009 at 12:14 PM, David MacIver <david [dot] maciver [at] gmail [dot] com> wrote:
2009/3/20 Russ Paielli <russ [dot] paielli [at] gmail [dot] com>:

> 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.
}


Andreas Hofstadler
Joined: 2009-02-26,
User offline. Last seen 42 years 45 weeks ago.
Re: [Fwd: Re: continue keyword]

Hi there.

I would love to have such simple and still readable coding standards to
follow.
The company I work for has some really strange coding standards:
1. every parameter must be prefixed by a P_ or even better by Pi_ or Pl_
or Ps_ for int, long and String. The type letters are optional. (puh)
2. every local variable must be prefixed by F_ and again with that silly
type letter.
3. private methods must be prefixed by an underscore
4. This one is no written down standard, but a coding practice found
extremely often:
private boolean _foo(Bar P_bar)
{
boolean Fb_ret = false;
if (P_bar != null)
{
Integer F_state = P_bar.getState();
if (F_state != null && F_state.equals(RUNNING))
{
Fb_ret = true;
}
}
return Fb_ret;
}

After checking, if null is ever possible I reduce such things to one
line and feel happy until I find the next piece of crap.

Here some code I refactored today:

public Todo[] getTodos()
{
Vector F_temp = new Vector(todos.size()); // todos is a
List

for (Object F_t : todos) //
Enhanced for loop was introduced by somebody else
{
F_temp.addElement(F_t);
}

Todo[] F_ret = new Todo[F_temp.getSize()];
F_temp.toArray(F_ret);
return F_ret;
}

Well, there is nothing I, or any other of the younger ones, could change
there as we have about 25000 Java files and multiple MegaLOCs of code
following this style.

greets

Andi

ps: I hate null

Ricky Clarkson schrieb:
> 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
>>>>>>
>>>>>>
>>>>
>>
>
>

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