Why does truth && "string" return "string"
Asked Answered
E

2

6

Let's say I have a something like

true && true #=> true

Which makes sense, so I try something like:

true && "dsfdsf" #=> "dsfdsf"

Which surprises me because often times I'll do something like if something && something and I always thought that that was evaluating to true and would return true. Further experimentation doing things like:

jruby-1.7.3 :009 > "ad" && "dsf"
 => "dsf" 
jruby-1.7.3 :010 > "ad" && "sdfd" && nil
 => nil 
jruby-1.7.3 :011 > "ad" && nil && "sdf"
 => nil 

makes it seem like Ruby returns either the last value if all are true or the first false value it finds. Why does it do this? and is this a correct mental model?

Enrica answered 28/3, 2014 at 15:7 Comment(2)
Read ruby.about.com/od/control/a/Boolean-Operators.htmLanger
It's the logically same behaviour. Values are truthy or falsey by themselves already. Why shouldn't the logical operators return them directly instead of having to return a separate boolean type?Aelber
W
10

Boolean operators in ruby are short-circuiting: if it is possible to determine the value of the expression from the left-hand argument, the right-hand argument isn't evaluated.

Therefore, a simpler mental model for evaluation of a boolean expression involving && is to consider first expressions involving only two operands: the left-hand operand is evaluated first; if the value of this operand is nil or false, the operand is returned and the right-hand operand isn't evaluated; if the left-hand operand is anything else, the right-hand operator is evaluated and its value is returned.

From this definition, it's clear that, as you note, expressions involving boolean operators don't return true or false, but simply a true value or a false value. It's worth noting that this doesn't make any difference in a context where a boolean expression is used only for its true-ness or false-ness.

Being the boolean operators left-associative, it's easy to determine the order of evaluation of an expression containing more than one operator, remembering that && has higher precedence than || (be careful however that and and or have the same precedence). Having done this, we can easily see that the value of the expression is the last evaluated element, i.e. the element that permits to determine the overall true-ness or false-ness of the expression.

In your examples (an expression composed only by && operators) the value of the expression is known as soon as the first false value is encountered, or after the last element has been evaluated as a true value; so, the last element evaluated will be the last element if all the elements preceding it are true valued, and the first false valued element if any is encountered.

You might wonder why the value of the expression isn't converted to true or false; actually, this kind of behavior can be used in idioms like

x = x || default

or the more brief

x ||= default

that is used to check if x is nil and, in that case, assign a default value to it.

Waddle answered 28/3, 2014 at 15:30 Comment(1)
It's interesting, while not directly related to the question, that x ||= default behaves differently from x = x || default because, if x is not nil or false, no assignment is performed. However it didn't feel right to me to present the latter without citing the other (and more frequent) idiom. Moreover, i believe this kind of behavior is actually possible in first place because it's in first place consistent with the expanded form, except possibly for the assignment.Waddle
C
1

Yes, it returns the last evaluated value. You can convert boolean if you want:

2.0.0p247 :016 > a = "s"
 => "s" 
2.0.0p247 :017 > !!a
 => true 
2.0.0p247 :018 > !!("ad" && nil && "sdf")
 => false

But this is not a nice solution. Try to use boolean types instead.

Cierracig answered 28/3, 2014 at 15:19 Comment(3)
This doesn't answer the question of why a string is returned instead of a boolean. He probably already knows how to convert to a boolean.Granthem
Only the first sentence is the answer.Cierracig
No, the first sentence is not an answer either. The question is WHY.Granthem

© 2022 - 2024 — McMap. All rights reserved.