10.times do |i|
puts 'too big' and break if i > 5
puts "#{i} ok"
end
I would expect this loop to quit after printing 0 to 5, but it executes
all 10 times. I know "puts" return nil, but isn't "and" (as opposed to
&&) supposed to execute both sides of the expression even if one side
evaluates to false?
Expected output:
0 ok
1 ok
2 ok
3 ok
4 ok
5 ok
too big
Actual output:
0 ok
1 ok
2 ok
3 ok
4 ok
5 ok
too big
6 ok
too big
7 ok
too big
8 ok
too big
9 ok
On Tue, Sep 28, 2010 at 2:03 PM, Jim Haungs <jhaungs@gmail.com> wrote:
10.times do |i|
puts 'too big' and break if i > 5
puts "#{i} ok"
end
I would expect this loop to quit after printing 0 to 5, but it executes
all 10 times. I know "puts" return nil, but isn't "and" (as opposed to
&&) supposed to execute both sides of the expression even if one side
evaluates to false?
No, the only difference between && and 'and' is their parsing precedence.
And nearly every time I've seen and used instead of && I've found a bug.
···
On Tue, Sep 28, 2010 at 4:03 PM, Jim Haungs <jhaungs@gmail.com> wrote:
10.times do |i|
puts 'too big' and break if i > 5
puts "#{i} ok"
end
I would expect this loop to quit after printing 0 to 5, but it executes
all 10 times. I know "puts" return nil, but isn't "and" (as opposed to
&&) supposed to execute both sides of the expression even if one side
evaluates to false?
Expected output:
0 ok
1 ok
2 ok
3 ok
4 ok
5 ok
too big
Actual output:
0 ok
1 ok
2 ok
3 ok
4 ok
5 ok
too big
6 ok
too big
7 ok
too big
8 ok
too big
9 ok
--
Posted via http://www.ruby-forum.com/\.
10.times do |i|
puts 'too big' and break if i > 5
puts "#{i} ok"
end
10.times do |i|
(puts 'too big'; break) if i > 5
puts "#{i} ok"
end
puts "done"
0 ok
1 ok
2 ok
3 ok
4 ok
5 ok
too big
6 ok
too big
7 ok
too big
8 ok
too big
9 ok
0 ok
1 ok
2 ok
3 ok
4 ok
5 ok
too big
done
···
On Tue, Sep 28, 2010 at 4:03 PM, Jim Haungs <jhaungs@gmail.com> wrote:
10.times do |i|
puts 'too big' and break if i > 5
puts "#{i} ok"
end
I would expect this loop to quit after printing 0 to 5, but it executes
all 10 times. I know "puts" return nil, but isn't "and" (as opposed to
&&) supposed to execute both sides of the expression even if one side
evaluates to false?
No that doesn't work, since puts returns nil and nil || whatever
doesn't evaluate whatever.
And
puts "Too big" || break if i > 5
Doesn't cause the break.
I think this is because break really isn't an expression.
The best solution seems to be
if i > 5
puts "Too big"
break
end
Both because it works, and I don't put too much weight on marginally
shorter code.
···
On Tue, Sep 28, 2010 at 4:14 PM, Kirk Haines <wyhaines@gmail.com> wrote:
On Tue, Sep 28, 2010 at 2:03 PM, Jim Haungs <jhaungs@gmail.com> wrote:
10.times do |i|
puts 'too big' and break if i > 5
puts "#{i} ok"
end
I would expect this loop to quit after printing 0 to 5, but it executes
all 10 times. I know "puts" return nil, but isn't "and" (as opposed to
&&) supposed to execute both sides of the expression even if one side
evaluates to false?
One sees control code like this in rails all the time:
redirect_to <somewhere> and return if <condition>
Never having looked at the return value from redirect_to (but guessing
it's always non-nil), I guess I assumed 'and' was the non-short-circuit
operator.
Otherwise, why this is idiom so prevalent? Because it looks more
English-like?
Rick Denatale wrote:
···
No, the only difference between && and 'and' is their parsing
precedence.
And nearly every time I've seen and used instead of && I've found a bug.
On Tue, Sep 28, 2010 at 4:03 PM, Jim Haungs <jhaungs@gmail.com> wrote:
No, the only difference between && and 'and' is their parsing precedence.
And nearly every time I've seen and used instead of && I've found a bug.
I use it sometimes for control flow in DSL-ish situations. Here's a
line from a toy recursive descent parser:
@sign *= -1 if lookahead == '-' and consume
Here, I use `and` specifically as a way to denote control flow. I
agree that encountering a line like this somewhere in the middle of a
generic codebase is very surprising and often puzzling, but in this
case it is a highly stylized codebase with its own idioms.
For example, that same parser also contains the line
while parse_digit; end
or this one
parse_string or parse_array
Again, I would *never* write something like this in generic code, but
in this particular case it is my specific idiom to encode the EBNF
rules
string | digit
and
digit*
This allows me to distinguish between infrastructure code that is
there to support the parser, and the actual parsing rules themselves,
since the former *always* uses parentheses, `&&`, `||` and `!` and the
latter always uses `and`, `or` and `not` and doesn't use parentheses.
One sees control code like this in rails all the time:
redirect_to <somewhere> and return if <condition>
Presumably that's in someone else's Rails application, not in Rails
itself.
That line is horrible. Firstly it's too clever, relying on relative
operator precedence between 'and' and 'if' which nobody remembers. And
secondly, it would break if there were ever a condition where
redirect_to did return false or nil(*).
But I understand the need for this pattern. I use this instead:
return redirect_to(<somewhere>) if <condition>
Regards,
Brian.
(*) IMO this is very dangerous, given that redirect_to doesn't even have
a documented return value:
Because it was the recommended way to get around 'double render'
errors in the early days of Rails, and yes and is more English-like.
The problem is that the and and or operators have a surprisingly low
precedence, so for example
a = 1
b = 2
x = a >0 and b < 1
sets x to true, then evaluates b < 1 returning false and throws the result away.
I've seen too many problems caused by this that I eschew and in favor
of && almost? everywhere in my ruby code.
···
On Tue, Sep 28, 2010 at 4:29 PM, Jim Haungs <jhaungs@gmail.com> wrote:
Interesting. Thanks.
One sees control code like this in rails all the time:
redirect_to <somewhere> and return if <condition>
Never having looked at the return value from redirect_to (but guessing
it's always non-nil), I guess I assumed 'and' was the non-short-circuit
operator.
Otherwise, why this is idiom so prevalent? Because it looks more
English-like?
Digging deeper into the ruby syntax, it does not appear that there are
any boolean operators that are not short-circuited. There are the
logical operators & and |, but those appear to work only with integers,
a la bit-masks.
Amazing how much you can still learn about the corners of this language
even after years of use.
···
I agree that's the clearest. For a one-liner I'd do: