Why can't I use "or" here?

(The problem is in both Ruby 1.8 and Ruby 1.9)

The expression:

puts(nil || 4)

works as expected. It prints ‘4’.

But this expression:

puts(nil or 4)

fails… it is a syntax error, for some mysterious reason.

Why? I thought the only diference between “or” and “||” is the
precedence.

On 31.12.2009 03:24, Albert S. wrote:

puts(nil or 4)

fails… it is a syntax error, for some mysterious reason.

Why? I thought the only diference between “or” and “||” is the
precedence.

Hm, on Ruby 1.9.1 I get:
irb(main):001:0> puts nil or 4

=> 4
irb(main):002:0> puts(nil or 4)
SyntaxError: (irb):2: syntax error, unexpected keyword_or, expecting ‘)’
puts(nil or 4)
^
from C:/Ruby19/bin/irb:12:in `’
irb(main):003:0> puts(nil || 4)
4
=> nil

This seems like a bug to me, since parenthesis should “only” make
method calls and precedent unambigious.

Albert S. wrote:

[…]
puts(nil or 4)

fails… it is a syntax error, for some mysterious reason.

Why? I thought the only diference between “or” and “||” is the
precedence.

Looks like a genuine bug to me. I can verify that behavior in MRI,
YARV, JRuby, IronRuby and Rubinius (which is not terribly surprising
since they all use the exact same parser).

I’d be interested in XRuby, since that’s the only sort-of complete
(well, for a very generous definition of “complete”, anyway) Ruby
implementation I know of which has its own parser. (Tinyrb has its own
parser, but it doesn’t have full syntax compatibility as a goal
anyway. Cardinal also has its own parser, AFAIK, but it’s a loong
way from being syntax-complete.)

jwm

On 2009-12-31, Phillip G. [email protected] wrote:

Hm, on Ruby 1.9.1 I get:
irb(main):001:0> puts nil or 4

=> 4

Note that this is equivalent to “puts nil” followed by “4”.

That’s significant.

Consider:
irb(main):001:0> x = nil or 4
=> 4
irb(main):002:0> x
=> nil

The grouping is:
(x = nil) or (4)

Or
(puts nil) or (4)

This seems like a bug to me, since parenthesis should “only” make
method calls and precedent unambigious.

I believe that’s precisely the problem – the precedence of “or” is
low enough that it can’t occur inside a method argument.

Compare this with the similar situation in C, where a comma operator
cannot occur inside an argument list for a function, because it’s part
of the function-call syntax. So:

valid C:
x = 1, y = 2;

(this performs both assignments, and returns the value of y after the
assignment, which happens to be 2.)

printf(“%d\n”, x = 1, y = 2);

This probably prints 1, but I think it’s undefined behavior because
there’s
excess arguments to printf. (I’m not sure whether that’s permitted or
not,
but my guess would be “no, but it probably always works”.)

So try:

irb(main):003:0> puts( (nil or 4) )
4
=> nil

Basically, if you really want parentheses (as in the precedence-changing
operator), you need to include them… Not merely put something that
can’t
go in a method argument list inside the confusingly-similar-looking
() which surround method arguments.

-s

On Wednesday 30 December 2009 08:35:43 pm Phillip G. wrote:

=> 4
irb(main):002:0> puts(nil or 4)
SyntaxError: (irb):2: syntax error, unexpected keyword_or, expecting ‘)’
puts(nil or 4)
^
from C:/Ruby19/bin/irb:12:in `’
irb(main):003:0> puts(nil || 4)
4
=> nil

Specifically, the parens around the method call. Want to see something
even
weirder?

irb(main):001:0> puts(nil or)
SyntaxError: (irb):1: syntax error, unexpected keyword_or, expecting ‘)’
puts(nil or)
^
from /home/ruby19/bin/irb:12:in <main>' irb(main):002:0> puts(nil or 4) SyntaxError: (irb):2: syntax error, unexpected keyword_or, expecting ')' puts(nil or 4) ^ from /home/ruby19/bin/irb:12:in
irb(main):003:0> (nil or 4)
=> 4
irb(main):004:0> puts((nil or 4))
4
=> nil
irb(main):005:0>

On Dec 30, 2009, at 9:24 PM, Albert S. wrote:

puts(nil or 4)

fails… it is a syntax error, for some mysterious reason.

Why? I thought the only diference between “or” and “||” is the
precedence.

Try:

puts((nil or 4))

I found a discussion of this in:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/38272

Gary W. wrote:

On Dec 30, 2009, at 9:24 PM, Albert S. wrote:

puts(nil or 4)

fails… it is a syntax error, for some mysterious reason.

Try:

puts((nil or 4))

I found a discussion of this in:
http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/38272

Thanks.

So it seems Ruby internally recognizes some structures as “statemenets”
and others as “expressions”. It seems disapointing at first, but since
Ruby supports precedence for operators (something Lisp doesn’t), there
has to be some price to pay.

On Thu, Dec 31, 2009 at 10:24 AM, Albert S. [email protected]
wrote:

Why? I thought the only diference between “or” and “||” is the
precedence.

yes, so you can do eg

system “pwd” or raise “no command here”
/home/botp
=> true

system “asdf” or raise “no command here”
RuntimeError: no command here

if you know perl, this is no surprise…

as always, there are many ways in ruby, you can use || or the double
parens override.

happy holiday and best regards
-botp

botp wrote:

On Thu, Dec 31, 2009 at 10:24 AM, Albert S. [email protected]
wrote:

Why? I thought the only diference between “or” and “||” is the
precedence.

yes, so you can do eg

system “pwd” or raise “no command here”
/home/botp
=> true

system “asdf” or raise “no command here”
RuntimeError: no command here

if you know perl, this is no surprise…

It is a surprise. In Perl, unlike in Ruby, func(0 or 1) does
work…

as always, there are many ways in ruby, you can use || or the double
parens override.

Well. it turns out there aren’t that many ways in ruby.

I originally tried to do the following:

some_func(ARGV[0] or raise “You must provide an argument”)

I wish it worked. But it doesn’t. So I changed it to:

some_func(ARGV[0] || raise “You must provide an argument”)

It still didn’t work. So finally I did:

some_func(ARGV[0] || (raise “You must provide an argument”))

It works. But, I must say, it isn’t as beautiful as my original plan. It
doesn’t read as English.

On 2009-12-31, Albert S. [email protected] wrote:

So it seems Ruby internally recognizes some structures as “statemenets”
and others as “expressions”. It seems disapointing at first, but since
Ruby supports precedence for operators (something Lisp doesn’t), there
has to be some price to pay.

I don’t think that’s it at all. I think it’s that methodname( is a
method
call (), not a grouping (). Thus the difference between
puts(a or b)
and
puts (a or b)

In short, it’s nothing to do with statements-vs-expressions, and
everything
to do with disambiguating method calls vs. parenthesized expressions.

-s

Seebs wrote:

On 2009-12-31, Albert S. [email protected] wrote:

So it seems Ruby internally recognizes some structures as “statemenets”
and others as “expressions”. It seems disapointing at first, but since
Ruby supports precedence for operators (something Lisp doesn’t), there
has to be some price to pay.

I don’t think that’s it at all. I think it’s that methodname( is a
method
call (), not a grouping (). Thus the difference between
puts(a or b)
and
puts (a or b)

In short, it’s nothing to do with statements-vs-expressions, and
everything
to do with disambiguating method calls vs. parenthesized expressions.

Interesting.

Why is the following a syntax error?

puts (123 if true)

and the following isn’t?

puts (123 or 456)

botp :

system “asdf” or raise “no command here”
RuntimeError: no command here

if you know perl, this is no surprise…

I know Perl, but I’m still surprised.

perl -le ‘print undef or 4’

perl -le ‘print(undef or 4)’

4

irb

irb(main):001:0> puts nil or 4

=> 4
irb(main):002:0> puts(nil or 4)
SyntaxError: (irb):2: syntax error, unexpected keyword_or, expecting ‘)’
puts(nil or 4)
^
from /usr/bin/irb:12:in `’

And if I “puts (nil or 4)” (there is a blank between them) will print 4.
(Just my thought,I was thinking this is a bug.)

Regards,
Jeff.

On 31.12.2009 06:32, Albert S. wrote:

It works. But, I must say, it isn’t as beautiful as my original plan. It
doesn’t read as English.

PS C:\Scripts> ruby .\unless.rb
./unless.rb:1: Argument error (RuntimeError)
PS C:\Scripts> ruby .\unless.rb “arg”
PS C:\Scripts> cat .\unless.rb
raise “Argument error” unless ARGV[0]
PS C:\Scripts>

I prefer it that way. :slight_smile:

Works in 1.8.6 and 1.9.1, too, to my great relief.

Albert S. wrote:

Well. it turns out there aren’t that many ways in ruby.

I originally tried to do the following:

some_func(ARGV[0] or raise “You must provide an argument”)

I wish it worked. But it doesn’t. So I changed it to:

some_func(ARGV[0] || raise “You must provide an argument”)

It still didn’t work. So finally I did:

some_func(ARGV[0] || (raise “You must provide an argument”))

It works. But, I must say, it isn’t as beautiful as my original plan. It
doesn’t read as English.

Hey, I now see that this works:

some_func((ARGV[0] or raise "You must provide an argument"))

Great. On the other hand, I won’t be able to remember this the next time
I need it.

Seebs wrote:

On 2009-12-31, Albert S. [email protected] wrote:

Interesting.

Why is the following a syntax error?

puts (123 if true)

and the following isn’t?

puts (123 or 456)

The if modifier has to go on the tail end of the containing complete
expression.

Then why does the following work?

a = (123 if true)

On 2009-12-31, Albert S. [email protected] wrote:

Interesting.

Why is the following a syntax error?

puts (123 if true)

and the following isn’t?

puts (123 or 456)

The if modifier has to go on the tail end of the containing complete
expression. You could say “statement”, but I don’t think that really
adds anything.

But that’s not the same issue as why “or” doesn’t work in a method
argument
without extra ().

-s

Seebs wrote:

On 2009-12-31, Albert S. [email protected] wrote:

So it seems Ruby internally recognizes some structures as “statemenets”
and others as “expressions”. It seems disapointing at first, but since
Ruby supports precedence for operators (something Lisp doesn’t), there
has to be some price to pay.

I don’t think that’s it at all. I think it’s that methodname( is a
method
call (), not a grouping (). Thus the difference between
puts(a or b)
and
puts (a or b)

In short, it’s nothing to do with statements-vs-expressions, and
everything
to do with disambiguating method calls vs. parenthesized expressions.

I don’t think there’s a disagreement between us:

Here is a method call in Ruby:

method_name ARG , ARG , ARG , …

ARG can be the expression “2”, for example. But is can’t be the
expression “2 or 3”. So the compiler has to classify “2 or 3” as
something that can’t stand for an ARG. So the compiler classifies it as
a STATEMENET and decides that a STATEMENT can stand for an ARG.

BTW, I can imagine why “2 or 3” couldn’t be a method argument. This
would only be possible if “or” has higher precedence than “,”, or else
func(1, 2 or 3, 4) would wreak havoc. But then do_this() or a, c = d,
ewould fail, because it'd mean(do_this() or a), c = d, e`.

On 31.12.2009 10:31, Albert S. wrote:

Then why does the following work?

a = (123 if true)

Because here you do an assignment.

Ruby Appliance’s Beginner VM will need a list of Ruby gotchas. :S

Phillip G. wrote:

On 31.12.2009 10:31, Albert S. wrote:

Then why does the following work?

a = (123 if true)

Because here you do an assignment.

My, my, my.

I can do this:

a = 999

and I can do this:

a = (123 if true)

so doens’t this mean that wherever I can put “999” I can also put “(123
if true)”?

In other words, why can I do this:

puts 999

But I can’t do this:

puts (123 if true)

???

Albert S. wrote:

[…]So the compiler has to classify “2 or 3” as
something that can’t stand for an ARG. So the compiler classifies it as
a STATEMENET and decides that a STATEMENT can stand for an ARG.

Oops. I meant “that a STATEMENT can’t stand for an ARG.”