Ruby: difference between &= and &&= - ruby

I have the impression I can use
bool &= true
# and
bool &&= true
# indifferently
Is there any difference between two? Is one solution unrecommended?
Actually
bool = true & false # false
So what's the difference between & and && in general? (I guess the same applies for ||)

Try the following:
x = 5
x |= 2
=> 7
|= and &= are equivalent to the bitwise x = x | 2 and x = x & 2
vs
x = 5
x ||= 2
=> 5
In the second statement, x ||= 2, it means x = 2 if x is nil, otherwise it's x.
( x = (x || 2) ; the expression x || 2 returns x if x is anything but nil otherwise it returns 2.
x ||= 'foo' is actually very common in Ruby (set x to foo is x is not already set)
x = (x & 3) (which is equivalent to x &= 3), returns 3 (the second operand) unless x is 0, it returns 0)
)
The same logic applies for & but it was easier to find an example on the top of my mind for |
=)

The main difference between the keywords is that the first | is a method, and can be redefined for a class, and the second || is not, and can be never defined as a method, and just used for language syntax, as you can see in example below:
Array.new.respond_to?( :| )
# => true
Array.new.respond_to?( :|| )
SyntaxError: (irb):35: syntax error, unexpected tOP_ASGN, expecting tSTRING_CONTENT or tSTRING_DBEG or tSTRING_DVAR or tSTRING_END
So, when you have applied the #| method it is able to return a value that differs from true, or false. Although for ruby's TrueClass, and FalseClass those values are true or false, but other descendants could redefine the return value, however, for Array and Set classes it implements functions similar to boolean bitwise operation. So can be sure that the true or false class's methods return also true or false. Otherwise, the keyword || is real language boolean operator, however it operates with values true, and not-true, you can see it on example:
'value1' || 'value2'
# => "value1"
true || false
# => true
'value1' || false
# => "value1"
false || 'value2'
# => "value2"
The return valus is always subordinated to logical expression, but the values of it are, as I denoted above, true, and not-true. Therefore you see in example return values not only of true/false pair, but of the real variable values too, and you can use it as if conditional operators as follows:
'value1' || 'value2'
and
if 'value1'
'value1'
else
'value2'
end
will return the same value.
According the or-equal assignment we see the following:
A |= false
# NameError: uninitialized constant A
a |= false
# false
A ||= false
# => false
In first case we are able to split |= operation into the two: call to #| method, and to assign the result to the variable. In the second case the ruby interpreter sees the whole operator ||=, verifies weither it is nil or undefined, and if yes assign to the variable or to the const the expression result.
The pair &, && has the same explanation.

When you are only using the & operator on boolean values, then there is no difference to &&, but if you want to use it with functions that return a boolean value then there is a difference. Have a look at this code:
def side_effect(message="hello")
puts message
true
end
#writes "hello" 2 times to the console and then returns false
false & side_effect & side_effect
# just returns false without writing "hello" to the console.
false && side_effect && side_effect

Related

Ruby ||= operator acting funny

From what I understand, a ||= 7 means the following:
if a has a value, continue using that value, but if it does NOT have one, then set it to 7.
Here is what happens though.
If i have a and b as:
a = true
b = false
then
a ||= b => true
(in my interpretation: since 'a' DOES have a value, it remains that, and does not get equated to 'false' - so far so good.)
However, if i have them switched up like:
a = false
b = true
then a ||= b => true
so in this case my logic does not work, since it should return false, as "since 'a' has a value, it should not be assigned the value of 'b'", which apparently happens here.
Am I missing something?
a ||= b
is equivalent to
a || a = b
this means b value is assigned to a if a is falsy, i.e. false or nil.

Need clarification on Ruby logical operators

Recently I started learning Ruby. I am practicing logical operators in irb and I got these results, which I don't understand. Can you please clarify these examples for me?
1 and 0
#=> 0
0 and 1
#=> 1
0 && 1
#=> 1
As opposed to other languages like C, in Ruby all values except for nil and false are considered “truthy”. This means, that all these values behave like true in the context of a boolean expression.
Ruby's boolean operators will not return true or false. Instead, they return the first operand that causes the evaluation of the condition to be complete (also known as short-circuit evaluation). For boolean and that means, it will either return the first “falsy” operand or the last one:
false && 1 # => false (falsy)
nil && 1 # => nil (falsy)
false && nil # => false (falsy)
1 && 2 # => 2 (truthy)
For boolean or that means, it will either return the first “truthy” operand or the last one:
false || 1 # => 1 (truthy)
nil || 1 # => 1 (truthy)
false || nil # => nil (falsy)
1 || 2 # => 1 (truthy)
This allows for some interesting constructs. It is a very common pattern to use || to set default values, for example:
def hello(name)
name = name || 'generic humanoid'
puts "Hello, #{name}!"
end
hello(nil) # Hello, generic humanoid!
hello('Bob') # Hello, Bob!
Another similar way to acheive the same thing is
name || (name = 'generic humanoid')
With the added benefit that if name is truthy, no assignment is performed at all. There is even a shortcut for this assignment of default values:
name ||= 'generic humanoid'
If you paid careful attention you will have noticed that this may cause some trouble, if one valid value is false:
destroy_humans = nil
destroy_humans ||= true
destroy_humans
#=> true
destroy_humans = false
destroy_humans ||= true
destroy_humans
#=> true, OMG run!
This is rarely the desired effect. So if you know that the values can only be a String or nil, using || and ||= is fine. If the variable can be false, you have to be more verbose:
destroy_humans = nil
destroy_humans = true if destroy_humans.nil?
destroy_humans
#=> true
destroy_humans = false
destroy_humans = true if destroy_humans.nil?
destroy_humans
#=> false, extinction of humanity digressed!
That was close! But wait, there is another caveat – specifically with the usage of and and or. These should never be used for boolean expressions, because they have very low operator precedence. That means they will be evaluated last. Consider the following examples:
is_human = true
is_zombie = false
destroy_human = is_human && is_zombie
destroy_human
#=> false
is_human = true
is_zombie = false
destroy_human = is_human and is_zombie
destroy_human
#=> true, Waaaah but I'm not a zombie!
Let me add some parentheses to clarify what's happening here:
destroy_human = is_human && is_zombie
# equivalent to
destroy_human = (is_human && is_zombie)
destroy_human = is_human and is_zombie
# equivalent to
(destroy_human = is_human) and is_zombie
So and and or are really just useful as “control-flow operators”, for example:
join_roboparty or fail 'forever alone :('
# this will raise a RuntimeError when join_roboparty returns a falsy value
join_roboparty and puts 'robotz party hard :)'
# this will only output the message if join_roboparty returns a truthy value
I hope that clarifies everything you need to know about these operators. It takes a bit of getting used to, because it differs from the way other languages handle it. But once you know how to use the different options, you've got some powerful tools at hand.
Both values are 'truthy' (in Ruby everything that isn't nil or false is truthy), so in all cases the second value is returned. On the contrary, if you use 'or', first value will be returned:
1 || 0 #=> 1
0 || 1 #=> 0
In Ruby both 0 and 1 is truth value. (Only nil and false are false value)
If both operands are truth value, and, && returns the last value.

Explain me about this simple ruby code [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I'm newbie in Ruby. What is printed and why?
a = nil
b = 2
a ||= b
puts a
explain me about this simple code.
2 is printed, because ||= assigns the right-hand value to the left-hand variable when the left-hand variable is nil or false. a is nil, so 2 will be assigned to a. Therefore 2 is printed.
A lot of programming requires understanding Boolean logic, basically how true and false values are determined, which are what trigger conditional logic to branch, loop, etc.
Consider this:
In Ruby there are true and false values, which have equivalent reserved words of true and false (it actually goes deeper than this but that's for a different time.):
true # => true
false # => false
Only nil and false are false values in Ruby, everything else is true. This differs from some other languages, like Perl, which thinks that 0 and '' (empty string) are also false. Remember though, only nil and false in Ruby are false.
The "not" values (AKA, opposites) of true and false are false and true respectively. The ! (Boolean "NOT") operator is used for this:
!true # => false
!false # => true
Now, this is a trick you'll see advanced programmers use: NOT-ing them twice returns a boolean version of their original values:
!!true # => true
!!false # => false
This is an important thing to understand. We can use !! on values besides true/false and determine whether they are true or false values:
!!'' # => true # !> string literal in condition
!!0 # => true # !> literal in condition
!!'foo' # => true # !> string literal in condition
!!1 # => true # !> literal in condition
Ruby isn't too happy about me using a literal for the test, but you can see that the above are all true, and these are false:
!!false # => false
!!nil # => false
Hopefully you see how we have to look at values in a language two ways, whether they're true/false and what their actual value is.
Moving on:
The || (Boolean "OR") looks at the left value first. If it's true it returns that value. If it's false, it looks at the right side and returns that:
true || false # => true
false || true # => true
nil || 'foo' # => "foo"
false || 2 # => 2
The ||= operator behaves similarly, only after the comparison, it assigns to the variable on the left if it was a false-type value:
a = false
a ||= true
a # => true
a = true
a ||= false
a # => true
Assigning to variables, instead of testing directly against the literals, results in similar results:
a = nil # => nil
!a # => true
!!a # => false
b = 2 # => 2
!b # => false
!!b # => true
A bit more:
||= is used as shorthand to replace a little bit of if/then code:
a = nil # => nil
b = 2 # => 2
if !a
a = b
end
a # => 2
a = 1 # => 1
b = 2 # => 2
if !a
a = b
end
a # => 1
And all that leads up to the code you're trying to understand:
a = nil # => nil
b = 2 # => 2
a ||= b # => 2
I believe that ||= is a shorthand way of saying "if a is false assign it to..." in this case b
So
a = nil
b = 2
a ||= b
puts a
> 2
and
a = 4
b = 2
a ||= b
puts a
> 4

Ruby : Conditional initialization

I've read about conditional initialization in Ruby and
obj1 ||= Class1.new
is same as
obj1 ||obj1 = Class1.new
as everything is Ruby is an Object, I wonder why the following phrase raises a "NameError: undefined method or name...":
x || x = 10
but
x ||= 10
is a correct statement
In the first form, x is referenced first independently. Unlike the second form, x needs to be defined first or else it would raise an error.
> x = nil
=> nil
> x || x = 10
=> 10
The form x ||= 10 combines declaration and testing at the same time, so it doesn't generate an error whether x was already declared earlier or not.
defined?(x) || something
In your example, x does not exist. So you can't test what its' value is. Check to see whether it is defined. You can go further:
defined?(x) && x.nil? || x = 10
This will check to see if x is defined. If not, it will set x to 10. If x is defined, but has a nil value (also not useful), then x is also set to 10.
I've always thought of it as being equivalent to obj1 = obj1 || Class1.new, rather than obj1 || obj1 = Class1.new. This interpretation is more correct because it doesn't raise a NameError, and is consistent with the behavior of other operators which combine with =:
number = 1
number += 2 #=> 3
number -= 5 #=> -2
number *= 2 #=> -4
number /= 2 #=> -2
number **= 2 #=> 4
boolean = false
boolean ||= false #=> false
boolean ||= true #=> true
boolean &&= true #=> true
boolean &&= false #=> false
boolean &&= false #=> false
string = ""
string += "Hello" #=> "Hello"
string += ", world!" #=> "Hello, world!"
As for why obj1 || obj1 = Class1.new raises a NameError, it's because the part of that statement before the || operator is trying to reference obj1 before it's defined. obj1 = obj1 || Class1.new doesn't do that because it starts the assignment before referencing obj1.

Ruby OR || syntax with an object

I have seen this syntax in Ruby:
x = ary['value'] || Value.new
I get the part that if left side of the || is false, then the right side will be executed. But I do not get the part that:
false || (object) becomes (object)
I thought || should resolve to boolean. At least in most other languages. Why is Ruby resolving to an object.
Another similar question I also have:
'test' || true
=> "test"
How does 'test' get evaluated as true?
In Ruby nil and false is evaluates to false only always. Look below:
p a = nil || 2 #=> 2
p a = false || 2 #=> 2
p nil || false || 2 #=> 2
p '' || 2 #=> ""
For more reference look here True, False And Nil Objects In Ruby and Ruby short circuit "or" explanation
In Ruby, you have four cases:
False is false
True is true
Nil is false-y
Anything else is truth-y
So,
5 && 8 #=> 8
5 || false #=> 5
false || 5 #=> 5
(5 && 8) == true #=> false
!!(5 && 8) == true #=> true
!!(false || nil) == false #=> true
The great rule of thumb on boolean evaluation in Ruby is that only the objects NilClass and FalseClass are evaluated as false. Any other object, including String, is evaluated to true, even if it's empty.
In Ruby, as in most programming languages, some values are truthy, while others are falsey. A truthy value is true for the purposes of boolean evaluation, and likewise a falsey value is false.
However, the truthy value isn't actually cast to true and a falsey isn't cast to false, which lets the boolean expression evaluate to something useful, rather than a flat true or false.
nil and false are the only falsey values in Ruby. Note that 0 is truthy, unlike in most other languages.
See https://gist.github.com/jfarmer/2647362 for more details.
This is called short-circuiting.
Any expression formed by joining together other expressions with the || operator will be short-circuited, meaning it "stops" at the first truthy expression.
So consider this example:
nil || Value.new
The Ruby interpreter looks at nil first; then, since that is not truthy, it moves on to the next expression.
Now consider the example at the end of your question:
"test" || true
Ruby looks at "test" first; and since that is truthy, the evaluation stops there.
The same is true of the && operator, which is essentially the same short-circuiting logic but only stopping once it finds a falsey expression.
Take this example:
person && person.name
If person is nil, then the above expression will evaluate to nil since that is the first falsey expression.
On the other hand:
person && person.male? && person.name
Suppose person is not nil, but is female. Then (presuming male? returned false) the above expression would evaluate to false.
And of course, if no expression is falsey, then the && operator just gives you the last one (which is typically what you want).

Resources