Explain me about this simple ruby code [closed] - ruby

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

Related

Boolean behaving strange, logic issue

I'm having an issue with boolean expected behavior. I can make the desired result but I'm not sure why the strange behavior occurs. This produces a wrong result:
def palindrome?(string)
rev = string.reverse
if rev == string
true
else
false
end
end
palindrome?("abc") == false # => true
palindrome?("abcba") == true # => true
palindrome?("z") == true # => true
while this produces the correct result:
def palindrome?(string)
rev = string.reverse
if rev == string
true
end
end
palindrome?("abc") == false # => false
palindrome?("abcba") == true # => true
palindrome?("z") == true # => true
The following might be similar:
def nearby_az(string)
counter = 0
string = string.split("")
if string.count == 1
false
elsif (string.index("z") - string.index("a")) <= 3
true
else
false
end
end
nearby_az("a") == false # => true
nearby_az("z") == false # => true
Because Ruby method will return the result of executing the last expression. For this if statement:
if rev == string
true
end
it will return nil if rev != string.
Actually, your first function is producing the correct result. The problem is the second formula. It returns nothing if the string is not a palindrome; it only returns true if the string is a palindrome. Therefore,
palindrome?("abc") == false
for the second equation returns false because palindrome?("abc") returns nothing because "abc" is not a palindrome, and so it is not equal to false.
The second implementation of palindrome? will return nil if it is not a palindrome. Thus nil == false # => false. In Ruby, all functions return something although it may be nil.

Is this any condition type in ruby? !!() , !() , !0, !!0

I was just playing with irb. And I tried such syntax which returns me true/false
Can anyone please describe me why and how this behavior happened? Is this any condition type?
For Eg:
> !!()
=> false
> !()
=> true
> !0
=> false
> !!0
=> true
I appreciate if anyone can describe me this syntax.
()
# => nil
parenthesis are precedence 'operator', parenthesis with no expression return nil, as you see. So no wonder that:
!()
# => true
!!() # == !(!()) == !(true)
# => false
0 is truthy in Ruby (in fact, only nil and false are falsy):
puts 'truthy' if 0
truthy
# => nil
so the opposite of 0 is false:
!0
# => false
and !!0 is opposite to false:
!!0 # == !(!0) == !(false)
# => true
() evaluates as nil, which evaluates similar to false. Adding the ! Operator (once, twice, or however many times) simply changes false to true and true to false...

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.

Ruby boolean operator precedence, different behaviours

Why does precedence behave differently in the following code :
a = true or true and false
if a then
puts "Foo"
end
if true or true and false then
puts "Quux"
end
This only prints "Foo" and not "Quux".
E:\Home>ruby --version
ruby 1.9.3p392 (2013-02-22) [i386-mingw32]
E:\Home>ruby test.rb
Foo
The operator = has precedence over and and or (see there for instance). So in your first statement,
a = true
is evaluated before the rest. Hence, you set a to true.
Look at the operator precedence
http://www.techotopia.com/index.php/Ruby_Operator_Precedence
The order of evaluation is like this
(((a = true) or true) and false)
# a = true
if (true or true) and false then
# equivalent to
if true and false then
To get a more natural behaviour, use && and ||.
see here
2 and 7
#=> 7
2 or 7
#=> 2
2 or 7 and 12
#=> 12
2 or 7 or 12
#=> 2
2 or 7 and 12 or 10
#=> 12
true and true and false
#=> false
true or true or false
#=> true
true and true or false
#=> true
true or true and false
#=> false
true or true and false and true
#=> false
Summary :
(a) when you will use in an expression with only and operator value of the expression is always the last operand and the reverse is true for expression having only or operator.In case of Boolean the full expression will be evaluated.
(b) When an expression will have and and or mixed, evaluation will continue till the last and and its ROH operand will be the value of the expression(in case of Boolean last and RHO,LHO will be evaluated,after that result will be produced as Boolean operation rule.
Applying the rule of (b)
below code works:
if true or true and false then
puts "Quux"
end
#=> nil
a = true or true and false
#=> false
if a then
puts "Foo"
end
#Foo
#=> nil
Below code outputs Foo due to the precedence of = over and,or.
The expression a = true or true and false evaluates as follows applying the rule (b)
a = true or true and false
||
(a = true) or true and false
||
true and false
||
false
One more good application of rule (b)
if 2 and 3 or nil
p "hi"
end
#=> "hi"
if 2 or 3 and nil
p "hello"
end
#nothing printed

what is the difference between 'and' and '&&' in Ruby [duplicate]

What is the difference between the && and and operators in Ruby?
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".
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.
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!
|| 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/ .
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
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.
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
and checks only first condition and gives result
on other hand && strongly checks both conditions and gives logical result.

Resources