For ... else ... end

Hi!

I’ve seen a somewhat unique structure in python. The for - else - end
structure.
The else branch is executed, when the program ends the for loop
normally, without a break.

Is there a similar feature in ruby? Will ruby support it?

Gergo

±[Kontra, Gergely @ Budapest University of Technology and Economics]-+

    Email: kgergely@mcl.hu,  kgergely@turul.eet.bme.hu          |

URL: turul.eet.bme.hu/~kgergely Mobile: (+36 20) 356 9656 |
±------“Olyan langesz vagyok, hogy poroltoval kellene jarnom!”-------+
.
Magyar php mirror es magyar php dokumentacio: http://hu.php.net

Is there a similar feature in ruby? Will ruby support it?

Something like this ?

   j = 6
   catch(:out) do
      for i in 1..10
         throw :out if i == j
      end
      puts "after"
   end

Guy Decoux

Mon, 8 Jul 2002 21:29:53 +0900, ts decoux@moulon.inra.fr pisze:

Something like this ?

j = 6
catch(:out) do
for i in 1…10
throw :out if i == j
end
puts "after"
end

For me it’s lexically scoped, i.e. something like:

callcc do |out|
for i in 1…10
out.call if i == j
end
puts "after"
end

···


__("< Marcin Kowalczyk
__/ qrczak@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/

ts schrieb:

j = 6
catch(:out) do
for i in 1…10
throw :out if i == j
end
puts "after"
end

Heaven … this will recall the Misuse-of-exception Thread
I read some time ago somewhere in a Java forum.

argh

Det

ts schrieb:

j = 6
catch(:out) do
for i in 1…10
throw :out if i == j
end
puts "after"
end

Playing around a bit now I recognized
whats so irritating within me.

It is, that I primarily want to do a for loop
(an iterator, you can say ‘each’ too),
but this is not the main construct here.
Instead this is the catch, and the loop, which
is the active part of the problem definition
(no: solution definition) is plunged inside it.
(don’t know if I could express what I mean =%-P ).

And meditating over the big picture of
this code snipped I realized now, how
similar it looks to BASIC-like goto constructs:

for x to y step z
do

if abc
then
goto :out
endif
endfor
print "after"
out:

:slight_smile:

Bye
Det

:slight_smile:

IMO, this is not a misuse. The throw/catch construct is
separate from begin-rescue-end and is often used in Ruby
for this kind of control flow issue…

Java, by contrast, has only one mechanism.

I’m open to debate, though.

And by the way, the Pythonism originally referenced is
certainly more elegant than the throw/catch example. I
wonder if it’s useful enough to consider including?

Maybe it’s one of those things you don’t realize you need
until you have it.

Hal Fulton

···

----- Original Message -----
From: “Dirk Detering” detering@iskv.de
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, July 08, 2002 9:31 AM
Subject: Re: for … else … end

ts schrieb:

j = 6
catch(:out) do
for i in 1…10
throw :out if i == j
end
puts "after"
end

Heaven … this will recall the Misuse-of-exception Thread
I read some time ago somewhere in a Java forum.

argh

ts schrieb:

j = 6
catch(:out) do
for i in 1…10
throw :out if i == j
end
puts "after"
end

I feel like such a novice… but would someone explain to me why such a
construction would be necessary? Specifically, for … else … end. What
is the difference between:

for x in (1…10)
puts x
else
puts "Done"
end

and

for x in (1…10)
puts x
end
puts “Done”

?

— SER

I feel like such a novice… but would someone explain to me why such a
construction would be necessary? Specifically, for … else … end. What
is the difference between:

for x in (1…10)
puts x
else
puts "Done"
end

and

for x in (1…10)
puts x
end
puts “Done”

My $0.02. Disclaimer: IDKP (I Don’t Know Python).

My understanding is that the for/else/end allows you
to distinguish between ‘normal’ termination of a loop
and ‘early’ termination. (Sometimes a useful thing, I
think.)

In other words, your examples above are exactly
equivalent, since there is no way for the loop to
terminate early.

I can’t think of an example right now, not even a
contrived one, but now that I reflect on it, there
are many times I want to detect ‘why’ a loop ended.
Maybe this would help.

Hal Fulton

···

----- Original Message -----
From: “Sean Russell” ser@germane-software.com
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, July 08, 2002 11:05 PM
Subject: Re: for … else … end

Sean Russell schrieb:

I feel like such a novice… but would someone explain to me why such a
construction would be necessary? Specifically, for … else … end. What
is the difference between:

[…Your example…]

(No difference here, as no break is used.)

Extract from the Python doc:

Loop statements may have an else clause; it is executed when the loop terminates through exhaustion of the list (with for) or when the condition becomes false (with while), but not when the loop is terminated by a break statement. This is exemplified by the following loop, which searches for prime numbers:

for n in range(2, 10):
… for x in range(2, n):
… if n % x == 0:
… print n, ‘equals’, x, ‘*’, n/x
… break
… else:
… # loop fell through without finding a factor
… print n, ‘is a prime number’

(REM: the range() function creates a list of items
excluding the end point. I.e.: n itself is not part
of the range ).

The situation that you want to know the exact
status after a loop is very common IMHO, and
is in classic languages (C, C++, Java, …)
typically solved by using flag variables like this:

for n in 2…9
myflag = 0
for x in 2…(n-1) # see remark above
var = n % x
if var == 0
print n, ’ equals ', x, " * ", n/x, "\n"
myflag = 1
break
end
end
if myflag == 0
# loop fell through without finding a factor
print n, " is a prime number\n"
end
end

HTH

Det

“Hal E. Fulton” schrieb:

[… Ruby code using catch/throw …]

IMO, this is not a misuse. The throw/catch construct is
separate from begin-rescue-end and is often used in Ruby
for this kind of control flow issue…

Ah, this calms me down :slight_smile: as it is a smart way.

Bye
Det

Hi,

···

In message “Re: for … else … end” on 02/07/09, “Hal E. Fulton” hal9000@hypermetrics.com writes:

And by the way, the Pythonism originally referenced is
certainly more elegant than the throw/catch example. I
wonder if it’s useful enough to consider including?

Maybe it’s one of those things you don’t realize you need
until you have it.

But I don’t feel “for … else” is intuitive. The “else” seem like
indentation mistake rather than loop termination hook. Maybe there
can be a more suitable keyword.

						matz.

Yukihiro Matsumoto schrieb:

But I don’t feel “for … else” is intuitive.

Yes, indeed. It is semantically very different to
the ‘else’ in an ‘if’ construct an does not support
natural language feelings.

The “else” seem like
indentation mistake rather than loop termination hook.

Yes, this too :slight_smile: .

Maybe there can be a more suitable keyword.

What about:

for i in (1…10)

… some code here

passed

… the no-break-received branch here

end

Bye
Det

And by the way, the Pythonism originally referenced is
certainly more elegant than the throw/catch example. I
wonder if it’s useful enough to consider including?

Maybe it’s one of those things you don’t realize you need
until you have it.

But I don’t feel “for … else” is intuitive. The “else” seem like
indentation mistake rather than loop termination hook. Maybe there
can be a more suitable keyword.

Hmm… I work around not having this construct constantly when doing
database work. After talking with Holden about this on IRC, I think
the following examples are helpful.

dbh.select_all(sql) do |row|

do something with row

else
puts "No rows returned!"
end

for elt in arr
puts elt
else
puts "No rows processed"
end

Which opens the door for:

for elt in arr
puts elt
else
puts "no rows"
ensure
puts "done looping"
end

Hmm… I think else is the correct word because it is short hand for
typing out:

if [].length > 0
for elt in []
puts elt
end
else
puts "now rows"
end
puts “done looping”

The example immediately above strikes me as a way of working around
the language, as opposed to the language doing what you want it to.
::shrug:: My $0.02. -sc

···


Sean Chittenden

At first, I didn’t think this kind of construct would be that useful, but
after some thought I can see that it might be a good addition. I can see it
being used in ‘for’ loop searching situations where ‘break’ is used when
some search criteria is met, found a string in a list for example. Normally
you’d achieve this with a boolean variable called something like ‘found’.

How about ‘default’ ?

for i in (0…9)
if (i == 5)
break
end
default
p "finished"
end

while i < 10
if ( i == 5 )
break
end
i += 1
default
p "finished"
end

It seems to make sense to use the same keyword that is used to provide
default behaviour for case constructs. However, Rubys equivilent of
’default’ clause for the case construct is actually the ‘else’ keyword! The
’when’ statements in a case construct are automatically doing a ‘break’ if
the condition is true. If none of the conditions are met ( a ‘break’ is not
done ), the ‘else’ clause executes. Logically, this is the same behaviour
that were looking for to extend loops.

Using ‘else’ would at least be consistent.

···


Justin Johnson

Why not :

“iterator … then … else … end”

while cond {

stuff

} then {

more stuff after succ. iteration

} else {

handle failed iteration

}

collection.each do |item|

handle item

then |collection|

handle collection after succ. iteration

else |collection|

handle collection after failed iteration

end

But then again, I get the feeling that instead of extending syntax for this
specific case there should be a way of defining your own control structures
by chaining blocks: (I believe SmallTalk has something like this?)

def iter &all then &ok else &err
ok = true
for x in @array
yield(x) &all || { yield(self) &err; ok = false; break }
end
yield(self) &ok if ok
end

collection.iter { |x|
break unless x.test
} then { |all|
all.stamp
} else { |all|
all.dump
}

– Nikodemus

···

On Tue, 9 Jul 2002, Yukihiro Matsumoto wrote:

But I don’t feel “for … else” is intuitive. The “else” seem like
indentation mistake rather than loop termination hook. Maybe there
can be a more suitable keyword.

I can’t say that I like the construct, although I can see its
utility. I’m also not sure that it fits into what I understand how
it would fit into Ruby’s idiom better than the catch-throw
mechanism.

The problem I have with it is that ‘for’ is (more or less) syntactic
sugar for ‘each’, isn’t it? It isn’t necessary to do:

for … do

end

Because it’s the same as:

…each do

end

Right? (The same applies to {} blocks.) How would you work an ‘else’
construct into a generic block, and what would it mean outside of an
’each’ or ‘for’ construction?

I freely admit that my understanding could be wrong, but that’s
where I think that this construct won’t work in Ruby. (I also think
that the keyword should be something other than ‘else’, but I’m not
sure what it should be. It’s something like a ‘finally if normal
termination’…)

-austin
– Austin Ziegler, austin@halostatue.ca on 2002.07.09 at 09.20.40

···

On Tue, 9 Jul 2002 16:33:48 +0900, Yukihiro Matsumoto wrote:

Hi,
In message “Re: for … else … end” > on 02/07/09, “Hal E. Fulton” hal9000@hypermetrics.com writes:

And by the way, the Pythonism originally referenced is certainly
more elegant than the throw/catch example. I wonder if it’s
useful enough to consider including?

Maybe it’s one of those things you don’t realize you need until
you have it.
But I don’t feel “for … else” is intuitive. The “else” seem like
indentation mistake rather than loop termination hook. Maybe there
can be a more suitable keyword.

Yukihiro Matsumoto wrote:

But I don’t feel “for … else” is intuitive. The “else” seem like
indentation mistake rather than loop termination hook. Maybe there
can be a more suitable keyword.

Here are the suggestions, so far:

    else
    ensure
    finally

I agree Jonas: it would be nice to have ‘else’ mean ‘if the loop was never
entered’; EG:

for x in some_array
# …
break if x == foo
else
puts "The array was empty"
finally # or ensure, which is already a Ruby keyword
puts "x was foo!"
end

I don’t know when I’d ever use ‘finally’, but I can think of many cases
where the ‘else’ would have saved me some time.

— SER

(Epiloque: argh Do not have time to reedit this mail now,
so take it as my loud thoughts).

Sean Chittenden schrieb:

for elt in arr
puts elt
else
puts "no rows"
ensure
puts "done looping"
end

Ahm, this seems a slightly different problem.
Here the else marks the case that the loop
never has been entered, not interrupted by ‘break’.

And what do you suggest with ‘ensure’ (“done looping”)
here?

(hum, took a look at the Exception description in pickaxe
for comparision):

f = File.open(“testfile”)
begin

… process

rescue

… handle error

else
puts "Congratulations-- no errors!"
ensure
f.close unless f.nil?
end

Here the else is described as:

The body of an else clause is executed only if no
exceptions are raised by the main body of code.
<<<<<

replacing ‘exceptions’ with ‘breaks’ of a for-loop
context would argue for ‘else’ to work like in Python.
Then there would be consistency between ‘else’ in 'begin’
and ‘else’ in a ‘for’ loop.

OTOH: What matches better to natural understanding?
The ‘else’ in a ‘begin’ context is naturally bound to
’rescue’. So you say:
BEGIN a process, do RESCUE for any exceptions ELSE
do something else.

But you naturally would not expect a for loop to break
but to pass. Therefore saying:
Do a process FOR every item in a list ELSE do something
(Python interpretation of ‘else’ ) seems confusing.

Defining a for loop as non-passing in normal situations
would cause the following sematic:

FOR every item in list do a process.
if INTERRUPTED do something ELSE do some other thing.

But this looks very similar to the Exception context.

Saying:
FOR every item in list do a process
when PASSED do something ELSE do some other thing.

causes the converse semantic: a for loop normally passes.

But in both cases the ‘else’ relates to the hook used before
(either INTERRUPTED or PASSED) and not directly to the FOR.
This correlates with the Exception semantic, where the 'else’
refers to the ‘rescue’ and not to the ‘begin’.

Regarding the ‘ensure’ …
I think I did not understand if it is a necessary
part or only declarative sugar, as IMHO every
code after the end is run in either case.

So writing:

f = File.open(“testfile”)
begin
# … process
[…]
ensure
f.close
end

or writing:

f = File.open(“testfile”)
begin
# … process
[…]
end
f.close

should be identical (?)

Bye
Det

Hi –

Hmm… I work around not having this construct constantly when doing
database work. After talking with Holden about this on IRC, I think
the following examples are helpful.

dbh.select_all(sql) do |row|

do something with row

else
puts "No rows returned!"
end

To me this introduces a seriously criss-crossed quality to the logic
flow. You’d end up with things like:

arr = [1,2,3,4]
f = arr.find_all {|n| n > 4 else puts “Not found”}

for elt in arr
puts elt
else
puts "No rows processed"
end

Which opens the door for:

for elt in arr
puts elt
else
puts "no rows"
ensure
puts "done looping"
end

Hmm… I think else is the correct word because it is short hand for
typing out:

if [].length > 0
for elt in []
puts elt
end
else
puts "now rows"
end
puts “done looping”

The example immediately above strikes me as a way of working around
the language, as opposed to the language doing what you want it to.
::shrug:: My $0.02. -sc

puts if arr.empty? then “no rows” else arr end
puts “done looping”

(Couldn’t resist :slight_smile:

How about:

if arr.empty?
puts "no rows"
else
for elt in arr
# do stuff
end
end

But in any case, I agree with Det who pointed out that this
(determining whether a loop is executed/entered at all) is different
from the ‘break’-trapping scenario.

David

···

On Tue, 9 Jul 2002, Sean Chittenden wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Austin Ziegler schrieb:

I can’t say that I like the construct, although I can see its
utility. I’m also not sure that it fits into what I understand how
it would fit into Ruby’s idiom better than the catch-throw
mechanism.

To repeat myself:

What possibilities does Ruby currently have to
express the following scheme completely?
(parts of it have just been shown in this
thread):

iterate over elements in container
if no elements were found do …
if loop completes without break do …
if loop has been interrupted with break do …

Can all this easily be expressed via catch/throw ?

We should create a complete example.
(Although I don’t think that all branches
would be used at the same time … (?) ).

The problem I have with it is that ‘for’ is (more or less) syntactic
sugar for ‘each’, isn’t it?

As I said before: Must this stay to be sugar for each ? or
can it be sugar for catch/throw too?
And:
Must this stay to be only syntactic sugar?
Or can it become more, up to an own syntax construct?

And:
Well, I’m now interested in this ‘more or less’.
For example scoping seems to be one difference…

It isn’t necessary to do:

for … do

end

Because it’s the same as:

…each do

end

Regarding the readability, yes. But it seems to
have effect on the ‘…’ inside this construct.

Bye
Det