Another logical precedence question

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’?

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

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.

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/

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
[email protected]