Strange behavior of or condition in loop

I don’t understand why ruby’s “or” acts differently in a loop.

This is some code I pulled out of a rails model, expanded the
assignments and simulated in IRB (1.8.7 and 1.9.2rc)

#simple boolean assignments
#Why does this work

dirty = false
found = true
dirty = dirty or found
puts dirty.to_s => true

#same type of assignments in loop giving meaning to dirty and found
#But this does not

a = [“score_method”, “updated_at”]
dirty = false
a.each{|attrib|
puts dirty.to_s + " in "
found = !( /score_method|weight|critical|minimum_value/i =~
attrib ).nil?
dirty = dirty or found
puts dirty.to_s + " out " + found.to_s
}
puts dirty.to_s => false

#another version with parens around or
#But this does

a = [“score_method”, “updated_at”]
dirty = false
a.each{|attrib|
puts dirty.to_s + " in "
found = !( /score_method|weight|critical|minimum_value/i =~
attrib ).nil?
dirty = (dirty or found)
puts dirty.to_s + " out " + found.to_s
}
puts dirty.to_s => true

I’ve been doing to additive boolean assignment stuff forever without
parens. Guess I just don’t understand Ruby.

and/or aren’t the same as &&/||. they have lower operator precedence
than
latter.

i recommend reading this article on the usage for both:

On Wed, Aug 18, 2010 at 12:40 AM, skim [email protected] wrote:

and/or aren’t the same as &&/||. they have lower operator precedence than
latter.

And to be particular for the OP’s problem “and” and “or” have lower
precedence than “=” assignment. (And have the same precedence as each
other.) So
dirty = dirty or found
is being parsed as
(dirty = dirty) or found
But since “&&” has a higher precedence than “||” which has a higher
precedence than “=” assignment, if you replaced the “or” in the
unbracketted
version by “||” you should now get the results of the bracketted
version.
(At least, it worked for me just now.)

skim: Thanks for the link - I mostly use “&&” and “||” (and sometimes
also
parentheses just to be sure and to be explicit) but the explanations of
the
history will probably make it easier for me to remember the precedence
of
“and” and “or” when I see them being used.

On Aug 17, 7:09 pm, Colin B. [email protected] wrote:

is being parsed as
(dirty = dirty) or found
But since “&&” has a higher precedence than “||” which has a higher
precedence than “=” assignment, if you replaced the “or” in the unbracketted
version by “||” you should now get the results of the bracketted version.
(At least, it worked for me just now.)

skim: Thanks for the link - I mostly use “&&” and “||” (and sometimes also
parentheses just to be sure and to be explicit) but the explanations of the
history will probably make it easier for me to remember the precedence of
“and” and “or” when I see them being used.

Thanks for the reply, explanation and link. I knew they had different
precedence, but I never looked them up but figured they’d be next to
each other. Never crossed my mind that assignment would have a higher
precedence.

A little disappointed in that I was happy to see “and” and “or”
because I never liked the symbol operators. Not so much that they are
bad, but one language uses & and another uses && and “and” just seems
so much clearer.

I hopefully will remember the next time, but may just use parentheses
to keep my mind straight.

Steve A.

AppleII717 wrote:

I don’t understand why ruby’s “or” acts differently in a loop.

This is some code I pulled out of a rails model, expanded the
assignments and simulated in IRB (1.8.7 and 1.9.2rc)

#simple boolean assignments
#Why does this work

dirty = false
found = true
dirty = dirty or found
puts dirty.to_s => true

A lot of great info in here but I was left with a question:

Why did it work outside the loop (in the example given above) but not
inside the loop? So I tried the inside the loop code both in irb and
from a file (using 1.9.1) and I got false, not true. See the irb session
below. It makes me feel better that it works the same way in both
instances.

AppleII717, are you sure you got ‘true’ in the code above? Note that
there is a ‘true’ output, but I think that it is because (dirty = dirty)
or found returns true, but dirty is false.

irb(main):001:0> dirty = false
=> false
irb(main):002:0> found = true
=> true
irb(main):003:0> dirty = dirty or found
=> true
irb(main):004:0> dirty
=> false
irb(main):005:0> dirty.to_s
=> “false”
irb(main):006:0>

js

On Wed, Aug 18, 2010 at 6:06 AM, John S. [email protected]
wrote:

found = true
instances.
=> true
irb(main):004:0> dirty
=> false
irb(main):005:0> dirty.to_s
=> “false”
irb(main):006:0>

~$ irb
irb(main):001:0> dirty = false
=> false
irb(main):002:0> found = true
=> true
irb(main):003:0> dirty = dirty or found
=> true
irb(main):004:0> dirty
=> false

This works as expected in Ruby 1.8.7.

Jesus.

On 8/17/10, AppleII717 [email protected] wrote:

dirty = dirty or found

I recommend you write it this way instead:

dirty ||= found

John S. wrote:

Why did it work outside the loop (in the example given above) but not
inside the loop? So I tried the inside the loop code both in irb and
from a file (using 1.9.1) and I got false, not true. See the irb session
below. It makes me feel better that it works the same way in both
instances.

Just to clarify: I meant I tried the outside the loop code in irb, not
the inside the loop code. Sorry, it was late last night.

The output agrees with Jesus’ out put above.

js