Feature #3232

Loops (while/until) should return last statement value if any, like if/unless

Added by Benoit Daloze almost 4 years ago. Updated almost 3 years ago.

[ruby-core:29920]
Status:Rejected
Priority:Normal
Assignee:-
Category:core
Target version:2.0.0

Description

=begin
In conditions:
if true
2
end #=> 2

In loops:
i = 0
while i < 3
i += 1
"return value"
end #=> nil

I suggest the return value of loops to be the return value of
the last "block" evaluated between "while/until" and "end".

It would be nil if the condition is not met from the first evaluation.

Is this reasonable to implement ?

It would come very handy in situations like:
while condition
...
mymethodreturnvalue
end
my
methodreturnvalue

because you could remove the last line.

The idea came up on ruby-talk: http://www.ruby-forum.com/topic/208978

Any thoughts?

Regards,
B.D.
=end

History

#1 Updated by Yukihiro Matsumoto almost 4 years ago

=begin
Hi,

In message "Re: [Feature #3232] Loops (while/until) should return last statement value if any, like if/unless"
on Sun, 2 May 2010 04:14:10 +0900, Benoit Daloze redmine@ruby-lang.org writes:

|In conditions:
|if true
| 2
|end #=> 2
|
|In loops:
|i = 0
|while i < 3
| i += 1
| "return value"
|end #=> nil
|
|I suggest the return value of loops to be the return value of
|the last "block" evaluated between "while/until" and "end".

The last evaluated expression in this case is "i < 3", so the loop
statement would have the return value of false value, even if it would
return the last value.

                        matz.

=end

#2 Updated by Kornelius Kalnbach almost 4 years ago

=begin
On 02.05.10 01:56, Yukihiro Matsumoto wrote:

The last evaluated expression in this case is "i < 3", so the loop
statement would have the return value of false value, even if it
would return the last value.
So, shouldn't it return false then?

[murphy]

=end

#3 Updated by Tomas Matousek almost 4 years ago

=begin
It returns the argument of break:

x = while true; break 123; end #=> 123

If you don't break out of the loop it makes sense that the result is nil.

Tomas

-----Original Message-----
From: Kornelius Kalnbach [mailto:murphy@rubychan.de]
Sent: Saturday, May 01, 2010 9:40 PM
To: ruby-core@ruby-lang.org
Subject: Re: [Feature #3232] Loops (while/until) should return last statement value if any, like if/unless

On 02.05.10 01:56, Yukihiro Matsumoto wrote:

The last evaluated expression in this case is "i < 3", so the loop
statement would have the return value of false value, even if it would
return the last value.
So, shouldn't it return false then?

[murphy]

=end

#4 Updated by Benoit Daloze almost 4 years ago

=begin
On 2 May 2010 01:56, Yukihiro Matsumoto matz@ruby-lang.org wrote:

Hi,

The last evaluated expression in this case is "i < 3", so the loop
statement would have the return value of false value, even if it would
return the last value.

                                                       matz.

My bad, I forgot about condition evaluation.
But that result is really not interesting, as it will always be false
(or true for until).

Is is possible, then, to keep the result of the last expression in the
loop, before it fails?

It returns the argument of break:
x = while true; break 123; end #=> 123
If you don't break out of the loop it makes sense that the result is nil.

Sure, so a way to solve my example would be:

i = 0
loop do
i += 1
break "return value" unless i < 3
end #=> "return value"

But there are a few disadvantages to use this way:
- using 'loop' and 'break', while you perfectly now when you want to stop
- therefore you need an 'unless', or the negative condition of what
you expected to write after while/until
- you need to specify again explicitly the return value to break, so
you don't use any shortcut.

But my example is not clear, let's see this one:

def method
array = []
while
array << do_sth
# With loop & break, here would be: break array unless
end
array # I would like to remove this "superfluous" statement
end

This would be a nice feature, and would remove the need to explicitly
mention the return value, again after the loop.

I think it would be more consistent with if/unless
(even if that case is simpler because it is actually the last
evaluated expression).

It would be a kind of inject/eachwithobject, but with a condition
instead of an Enumerable (and no initial value).

B.D.

=end

#5 Updated by Nobuyoshi Nakada almost 4 years ago

=begin
Hi,

At Sun, 2 May 2010 19:20:41 +0900,
Benoit Daloze wrote in :

Is is possible, then, to keep the result of the last expression in the
loop, before it fails?

Possible.
http://github.com/nobu/ruby/commit/b83915dda5645d57f83947bc948abe76fcae59e0

def method
array = []
while
array << do_sth
# With loop & break, here would be: break array unless
end
array # I would like to remove this "superfluous" statement
end

This would be a nice feature, and would remove the need to explicitly
mention the return value, again after the loop.

It feels too confusing to me.

--
Nobu Nakada

=end

#6 Updated by Benoit Daloze almost 4 years ago

=begin
On 2 May 2010 15:24:52 UTC+2, Nobuyoshi Nakada nobu@ruby-lang.org wrote:

It feels too confusing to me.

Nobu Nakada

Thanks for the patch, Nobu.

So, how would this cause unexpected behavior ?

Let's say 'ret' is the return value of the last statement in the body
of the loop.

  • If 'break' is not used in the loop (while/until), it will now result
    in 'ret', or false if never evaluated.

    Before, it always returned nil, which is not interesting and should
    never have been used.
    So that case is not relevant I think.

  • if 'break' is used, it can return 'ret' ,
    if the condition of the loop is met before break's condition.

    So:
    i = 0
    ret = while i < 3
    i += 1
    break "break" if i > 3
    "loop return value"
    end #=> ret = "loop return value" instead of nil

    Would someone check for 'ret' to be nil?
    Is there any real use case of using 'ret' (which would be nil) in this
    situation ?

    I think if you don't break, you would not use any value depending on
    the return value of the loop.

    Please say if you think this can break compatibility, and of course
    any opinion is appreciated !

    Regards,
    B.D.

=end

#7 Updated by Yukihiro Matsumoto almost 4 years ago

=begin
Hi,

In message "Re: Re: [Feature #3232] Loops (while/until) should return last statement value if any, like if/unless"
on Mon, 3 May 2010 05:10:30 +0900, Benoit Daloze eregontp@gmail.com writes:

|So, how would this cause unexpected behavior ?

It is neither consistent (other statements returns the value from the
"last" expression), nor useful (by returning nil, you can use the
value from break safely), nor compatible.

                        matz.

=end

#8 Updated by Benoit Daloze almost 4 years ago

=begin
Hi,

|On 3 May 2010 02:15, Yukihiro Matsumoto matz@ruby-lang.org wrote:
|Hi,
|
|It is neither consistent (other statements returns the value from the
|"last" expression),

Actually it is not, but here the value of the "last" expression is
always false/true, so really not interesting
(and it returns nil, so it's neither consistent now about that)

| nor useful (by returning nil, you can use the
|value from break safely), nor compatible.

That's the problem.
The idea was: I think nobody wrote code using the fact it is nil if
the loop did not break.

But it is useful:
it adds a useful return value to the loop,
which it does not have (nil), except if 'break' is used.

| matz.

I suppose you've got the final point, and I do agree it can be
confusing/inconsistent.

My idea was more of a thought, but the result is interesting though
(and could be useful for me (and some others I think)).

Special thanks to Nobu,
and thanks for sharing your thoughts.

Regards,
B.D.

=end

#9 Updated by Marc-Andre Lafortune almost 4 years ago

  • Status changed from Open to Rejected

=begin

=end

Also available in: Atom PDF