Mike W
Mike W

Reputation: 401

Evaluation of multiple conditions

I have a quick question :

In ruby, If I write

def test
  foo && a  == b && c == "bar"
end

if foo is null or false, will it keep evaluating the rest of the expression ?

Does it change anything if I do this instead

def test
  a == b && c == "bar" if foo
end

thanks a lot

Upvotes: 4

Views: 2879

Answers (2)

Eric Duminil
Eric Duminil

Reputation: 54303

Theory

&& is a lazy operator, just like ||.

It means that in a && b, if a is false or nil, Ruby won't bother to check b because a && b will be false/nil anyway.

This behaviour is actually desired, because it saves time and could avoid NoMethodErrors.

if a && method_which_requires_a_non_nil_parameter(a)
  # ...
end

method_which_requires_a_non_nil_parameter wouldn't be called at all if a is nil.

or :

x = x || long_method_to_calculate_x

is often used for caching, more often written as :

@x ||= long_method_to_calculate_x

Answer

def test
  foo && a  == b && c == "bar"
end

The rest of the expression won't be evaluated if foo is nil or false : a, b, c could even be undefined without raising a NameError.

def test
  a == b & c == "bar" if foo
end
  • If foo is truthy, the results will be exactly the same.

  • If foo is nil or false, the 2 equalities won't be evaluated, just like with the first example. But :

    • If foo is nil, both test will return nil.

    • If foo is false, first example will return false, second example will return nil.

Upvotes: 6

P.S.
P.S.

Reputation: 16412

"If foo is null or false, will it keep evaluating the rest of the expression?" No, it will not

This table should help you in such questions:

The following table is ordered according to descending precedence (highest precedence at the top)

N A M  Operator(s)            Description
- - -  -----------            -----------
1 R Y  ! ~ +                  boolean NOT, bitwise complement, unary plus
                              (unary plus may be redefined from Ruby 1.9 with +@)

2 R Y  **                     exponentiation
1 R Y  -                      unary minus (redefine with -@)

2 L Y  * / %                  multiplication, division, modulo (remainder)
2 L Y  + -                    addition (or concatenation), subtraction

2 L Y  << >>                  bitwise shift-left (or append), bitwise shift-right
2 L Y  &                      bitwise AND

2 L Y  | ^                    bitwise OR, bitwise XOR (exclusive OR)
2 L Y  < <= >= >              ordering

2 N Y  == === != =~ !~ <=>    equality, pattern matching, comparison
                              (!= and !~ may not be redefined prior to Ruby 1.9)

2 L N  &&                     boolean AND
2 L N  ||                     boolean OR

2 N N  .. ...                 range creation (inclusive and exclusive)
                              and boolean flip-flops

3 R N  ? :                    ternary if-then-else (conditional)
2 L N  rescue                 exception-handling modifier

2 R N  =                      assignment
2 R N  **= *= /= %= += -=     assignment
2 R N  <<= >>=                assignment
2 R N  &&= &= ||= |= ^=       assignment

1 N N  defined?               test variable definition and type
1 R N  not                    boolean NOT (low precedence)
2 L N  and or                 boolean AND, boolean OR (low precedence)
2 N N  if unless while until  conditional and loop modifiers

Upvotes: 1

Related Questions