Reputation: 87210
What is the difference between the &&
and and
operators in Ruby?
Upvotes: 386
Views: 217365
Reputation: 73
For me the behavior of and
as opposed to modifier if
is preferable if I want to exploit a side effect of the conditional expression - watch the undefined local variable or method 'y'
in the first attempt:
km@latika:~$ irb
irb(main):001:0> x=y if (y="hello")
(irb):1: warning: found `= literal' in conditional, should be ==
(irb):1:in `<main>': undefined local variable or method `y' for main:Object (NameError)
from /usr/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
from /bin/irb:25:in `load'
from /bin/irb:25:in `<main>'
irb(main):002:0> quit
At this point though y
is already assigned, so I restart irb
to demonstrate my point with a fresh start:
km@latika:~$ irb
irb(main):001:0> y="hello" and x=y
=> "hello"
irb(main):002:0> quit
In my opinion this is the nicest way to override a variable with something not nil (or false, but that is outside the point). Especially if instead of "hello"
we have complicated_calculation()
.
Upvotes: 0
Reputation: 407
and checks only first condition and gives result on other hand && strongly checks both conditions and gives logical result.
Upvotes: 1
Reputation: 2365
and
has lower precedence, mostly we use it as a control-flow modifier such as if
:
next if widget = widgets.pop
becomes
widget = widgets.pop and next
For or
:
raise "Not ready!" unless ready_to_rock?
becomes
ready_to_rock? or raise "Not ready!"
I prefer to use if
but not and
, because if
is more intelligible, so I just ignore and
and or
.
Refer to "Using “and” and “or” in Ruby" for more information.
Upvotes: 5
Reputation: 29094
and
has lower precedence than &&
.
But for an unassuming user, problems might occur if it is used along with other operators whose precedence are in between, for example, the assignment operator:
def happy?() true; end
def know_it?() true; end
todo = happy? && know_it? ? "Clap your hands" : "Do Nothing"
todo
# => "Clap your hands"
todo = happy? and know_it? ? "Clap your hands" : "Do Nothing"
todo
# => true
Upvotes: 23
Reputation: 99751
and
is the same as &&
but with lower precedence. They both use short-circuit evaluation.
WARNING: and
even has lower precedence than =
so you'll usually want to avoid and
. An example when and
should be used can be found in the Rails Guide under "Avoiding Double Render Errors".
Upvotes: 411
Reputation: 2174
I don't know if this is Ruby intention or if this is a bug but try this code below. This code was run on Ruby version 2.5.1 and was on a Linux system.
puts 1 > -1 and 257 < 256
# => false
puts 1 > -1 && 257 < 256
# => true
Upvotes: 0
Reputation: 16667
||
and &&
bind with the precedence that you expect from boolean operators in programming languages (&&
is very strong, ||
is slightly less strong).
and
and or
have lower precedence.
For example, unlike ||
, or
has lower precedence than =
:
> a = false || true
=> true
> a
=> true
> a = false or true
=> true
> a
=> false
Likewise, unlike &&
, and
also has lower precedence than =
:
> a = true && false
=> false
> a
=> false
> a = true and false
=> false
> a
=> true
What's more, unlike &&
and ||
, and
and or
bind with equal precedence:
> !puts(1) || !puts(2) && !puts(3)
1
=> true
> !puts(1) or !puts(2) and !puts(3)
1
3
=> true
> !puts(1) or (!puts(2) and !puts(3))
1
=> true
The weakly-binding and
and or
may be useful for control-flow purposes: see http://devblog.avdi.org/2010/08/02/using-and-and-or-in-ruby/ .
Upvotes: 43
Reputation: 81450
The Ruby Style Guide says it better than I could:
Use &&/|| for boolean expressions, and/or for control flow. (Rule of thumb: If you have to use outer parentheses, you are using the wrong operators.)
# boolean expression
if some_condition && some_other_condition
do_something
end
# control flow
document.saved? or document.save!
Upvotes: 69
Reputation: 211560
The practical difference is binding strength, which can lead to peculiar behavior if you're not prepared for it:
foo = :foo
bar = nil
a = foo and bar
# => nil
a
# => :foo
a = foo && bar
# => nil
a
# => nil
a = (foo and bar)
# => nil
a
# => nil
(a = foo) && bar
# => nil
a
# => :foo
The same thing works for ||
and or
.
Upvotes: 262