# Another logical precedence question

**URL:** <https://www.ruby-forum.com/t/another-logical-precedence-question/142408>\
**Category:** Ruby\
**Created:** [July 7, 2008, 5:32pm UTC](https://www.ruby-forum.com/t/another-logical-precedence-question/142408 "2008-07-07T17:32:01Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![S-jb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/43a26b/32.png) [@S-jb](https://www.ruby-forum.com/u/S-jb)\
**Post date:** [July 7, 2008, 5:32pm UTC](https://www.ruby-forum.com/t/another-logical-precedence-question/142408/1 "2008-07-07T17:32:01Z")

</div>

I am used to using the following shortcut:

value = ARGV.shift or usage

where usage is a method.  
However, I recently ran into a situation where the following did not  
work (as expected, anyway):

$user\_type = ARGV.shift or usage  
$user\_map = ARGV.shift or DEFAULT\_MAP

DEFAULT\_MAP is just a string constant. When I tried to access $user\_map  
later I was surprised to find that it was nil when no argument was  
provided. If I changed things to:

$user\_type = ARGV.shift or usage  
$user\_map = (ARGV.shift or DEFAULT\_MAP)

I got behavior I expected ($user\_map was assigned DEFAULT\_MAP).

Why the two types of behavior based (as far as I can tell) on the type  
of the second parameter to ‘or’?

---

<div class="post-metadata">

**Author:** ![S-jb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/43a26b/32.png) [@S-jb](https://www.ruby-forum.com/u/S-jb)\
**Post date:** [July 7, 2008, 5:55pm UTC](https://www.ruby-forum.com/t/another-logical-precedence-question/142408/2 "2008-07-07T17:55:50Z")

</div>

> I was surprised to find that it was nil when no argument was  
> provided. If I changed things to:
> 
> $user\_type = ARGV.shift or usage  
> $user\_map = (ARGV.shift or DEFAULT\_MAP)

Consider the following example:  
irb(main):001:0\> a = nil or 1  
=\> 1  
irb(main):002:0\> a  
=\> nil  
irb(main):003:0\> a = nil || 1  
=\> 1  
irb(main):004:0\> a  
=\> 1

So what you’re doing is  
(ut = ARGV.shift) or usage  
but I’m pretty sure that what you want to do is  
ut = ARGV.shift || usage

---

<div class="post-metadata">

**Author:** ![S-jb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/43a26b/32.png) [@S-jb](https://www.ruby-forum.com/u/S-jb)\
**Post date:** [July 7, 2008, 6:04pm UTC](https://www.ruby-forum.com/t/another-logical-precedence-question/142408/3 "2008-07-07T18:04:22Z")

</div>

ThoML wrote:

> So what you’re doing is  
> (ut = ARGV.shift) or usage  
> but I’m pretty sure that what you want to do is  
> ut = ARGV.shift || usage

I see.  
Invoking the call and invoking the string are NOT the same thing.  
_blush_  
Thanks for the help.

---

<div class="post-metadata">

**Author:** ![S-jb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/43a26b/32.png) [@S-jb](https://www.ruby-forum.com/u/S-jb)\
**Post date:** [July 7, 2008, 6:08pm UTC](https://www.ruby-forum.com/t/another-logical-precedence-question/142408/4 "2008-07-07T18:08:08Z")

</div>

On Jul 7, 2008, at 9:28 AM, -j b- wrote:

> Why the two types of behavior based (as far as I can tell) on the type  
> of the second parameter to ‘or’?

it’s always the _same_ behavior, namely

(something = this) or that

so when ‘that’ happens to be a method call which prints out usage and  
exits you get the behavior you want be accident, when you do

user\_map = ARGV.shift or DEFAULT\_MAP

you simply do this

cfp:~ \> irb

> > user\_map = nil or Hash.new  
> > =\> {}  
> > user\_map  
> > =\> nil

in otherwords

(user\_map = nil) or DEFAULT\_MAP

so the ‘or’ bit is essentially a noop you execute after assigning nil  
to the user\_map

regards.

a @ [http://codeforpeople.com/](http://codeforpeople.com/)

---

<div class="post-metadata">

**Author:** ![S-jb](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/43a26b/32.png) [@S-jb](https://www.ruby-forum.com/u/S-jb)\
**Post date:** [July 7, 2008, 6:06pm UTC](https://www.ruby-forum.com/t/another-logical-precedence-question/142408/5 "2008-07-07T18:06:22Z")

</div>

On Jul 7, 2008, at 11:28 AM, -j b- wrote:

> Why the two types of behavior based (as far as I can tell) on the type  
> of the second parameter to ‘or’?

If you choose to use ‘or’ rather than ‘||’, you are not just getting  
different precedence (‘or’ is lower than ‘||’), but there are a bunch  
of operators that fall in the middle.

In particular, the assignment operators are higher precedence than  
‘or’ and lower precedence than ‘||’.

So you really have:

(value = ARGV.shift) or (usage)  
($user\_type = ARGV.shift) or (usage)  
($user\_map = ARGV.shift) or (DEFAULT\_MAP)

When you change the operator to ‘||’, the precedence becomes the  
equivalent of:

value = (ARGV.shift || usage)  
$user\_type = (ARGV.shift || usage)  
$user\_map = (ARGV.shift || DEFAULT\_MAP)

Generally, the use of the ultra-low precedence ‘and’, ‘or’, ‘not’  
operators is best reserved for places where the precedence does what  
you expect. For me, this typically means thinking of these as  
combining “statements” (which are often either assignment or flow  
control) rather than expressions (for which I tend to always use ‘&&’,  
‘||’, ‘!’ although my background with C and Perl make this sub-  
conscious in most cases).

-Rob

Rob B. [http://agileconsultingllc.com](http://agileconsultingllc.com)  
removed\_email\_address@domain.invalid
