January 27, 2015 by Daniel P. Clark

or

Truthiness

Both or and || will return the first item that evaluates as true from the left side to the right.

true or "this doesn't return"
# => true
true || "this doesn't return"
# => true
false || true
# => true
false || false
# => false
false or false or 1 or 2
# => 1

In Ruby any Object that exists is considered true.  The only exceptions are false itself and nil.

nil || false or nil || 3
# => 3

Even unassigned symbols are considered true.

:x || 2
# => :x

So whenever an or comparison is done only nil and false will be false and the first thing that evaluates as true from left to right will be what is returned.

Bitwise Or

There are a few characters in Ruby that if you’ve used them with out knowing their behavior then you may have run into some “peculiar” behavior.  For example when you think about or you may think of 3 or so different ways of doing it or, ||, |.  But the single pipe or behaves differently when used.  For example:

1 or 2 # => 1 
1 || 2 # => 1 
1 | 2  # => 3 

As we continue with numbers the weirdness seems to prevail.

12 | 14 # => 14 
12 | 15 # => 15 
12 | 16 # => 28

The reason this isn’t behaving the same as the other ors we’re used to is because it’s a binary operator.  Binary numbers are a base 2 numbering system with only 1s and 0s.  The standard numbers we use are base 10 numbers.  When you use a binary operator on a base 10 number it converts the number into base 2 to do the calculation and then returns your number in the standard systems base 10 result.  In Ruby binary numbers are represented with a 0b at the beginning.  So the number zero is 0b0, the number one is 0b1, and the number two is 0b10.  Let’s write a method to convert our base 10 numbers into base 2.

def bin(x)
  "0b%b" % x
end

This method will represent all results as a binary result.

bin 7  # => "0b111" 
bin 8  # => "0b1000" 
bin 32 # => "0b100000" 

When using the bitwise or it compares each binary digit by position and it will return 1 in each answers position for where either of the inputs had 1.  For example:

bin 0b1110011 | 0b0001100 # => "0b1111111"
bin 0b1010 | 0b0001 # => "0b1011" 

So each binary number is compared and the on bits (1) are merged.  Lets look at why 12 | 16 became 28.

bin 12 # => "0b01100" 
bin 16 # => "0b10000" 
bin 28 # => "0b11100" 
bin 12 | 16 # => "0b11100" 

So you can clearly see the truth of each binary position was or-d over and all truths carried into the answer.

Bitwise or will still work for true false comparison

true | false
# => true
false | true
# => true
false | false
# => false

But it’s best not to use it for this kind of truth comparison as it is designed for bitwise operations.  You’ll be much safer using || or or.

Bitwise XOR

There is also a bitwise exclusive or (^).  This will return the “on” bits where only one digit per position is on.

bin 0b110011 ^ 0b010011 # => "0b100000"

Arrays

Now the behavior of single pipe or with Arrays seems peculiar to me.  For example:

[1] or [2] # => [1] 
[1] || [2] # => [1] 
[1] | [2]  # => [1, 2] 
[1,3,7] | [2,5]     # => [1, 3, 7, 2, 5] 
[1,3,7,5] | [2,5]   # => [1, 3, 7, 5, 2] 
[1,3,7,2] | [2,5]   # => [1, 3, 7, 2, 5]  
[1,3,7,2] | [2,5,7] # => [1, 3, 7, 2, 5] 

Here we see the single pipe or seems to merge Arrays but only keeps a unique result ordered by the first matching case.  Conversely bitwise operator and (&) returns a result of a unique result with common items.

[1,3,7,2] & [2,5,7] # => [7, 2] 

Boolean

Computers. of or relating to a data type having two possible values representing “true” or “false.”.

When writing code with or you are using boolean evaluation.  When you write your own methods that are explicitly returning either true or false you should use the question mark on the end of the method.  For example is_full? or winning? should always return either true or false.  Any method can be used in an or evaluation since everything is evaluated as true unless it’s nil or false, but it’s best not to use heavily active code in a truth comparison.

Assign before comparing:
# DON'T DO THIS
def waisted_resources
  #...
end

if waisted_resources || waisted_resources > 1
  puts "Wasted the following #{waisted_resources}"
end

Here the method waisted_resources is run 3 times.  It’s executed each time it’s called here, twice within the if before it’s run again to print out the result.  If you must reuse the value from a method first save it in a variable and then use it.

result = wasted_resources()
if result || result > 1
  puts "Wasted the following #{result}"
end

Or Assignment

When you want to assign a value to a variable but it may already have a value then you may want to use or-equals (||=).   Or-equals will only assign the value on the right side if the variable on the left is nil or not yet defined.

cow ||= "bovine"
# => "bovine"
cow ||= "cud chewer"
# => "bovine"

cow = nil
# => nil
cow ||= "cud chewer"
# => "cud chewer"

This is the same as

cow = cow || "bovine"

This method of saving a variable is known as Memoization.

Summary

When first learning to program the word or is the most straight-forward.  The single and double pipes seam a bit foreign and don’t seem to be very clear.  And after experimenting with them and finding strange behavior with the single pipe or, aka bitwise or, it may leave a bit of residual confusion.  So know that || and or are pretty much the same thing, and the bitwise or (|) is for binary “on” bit merging.  Or is one of the most common evaluations in programming, second only to and.

As always I hope this was both enjoyable and insightful for you.  Please comment, share, subscribe to my RSS Feed, and follow me on twitter @6ftdan!

God Bless!
-Daniel P. Clark

#bitwise#language xor#or#programming#ruby

Comments

  1. tdg5
    March 3, 2015 - 6:04 am

    Hey Dan,

    Nice introduction to the many flavors of or! It can definitely be confusing knowing which to use when. XOR in particular is a clever devil that I wish I had an excuse to use more often.

    Though they are fairly similar, I would caution you against or in favor of ||. Though or has a nicer semantic quality, the GitHub Ruby Styleguide (I’ve linked bbatsov’s fork because it includes links and examples), goes so far as to say:

    The and and or keywords are banned. It’s just not worth it. Always use && and || instead.

    Avdi Grimm has a couple of articles on the subject, the most recent of which, How to use Ruby’s English and/or operators without going nuts, offers some less extreme advice for when it might be appropriate to use and/or.

    Thanks for sharing!

    • Daniel P. Clark
      March 3, 2015 - 10:45 am

      Thanks for the heads up. I hadn’t known about the way and/or were implemented. And the link to Avdi’s article was very informative. Thanks for sharing it!

Leave a Reply

Your email address will not be published / Required fields are marked *