Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why can't I use "or" here?

0 views
Skip to first unread message

Albert Schlef

unread,
Dec 30, 2009, 9:24:26 PM12/30/09
to
(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.
--
Posted via http://www.ruby-forum.com/.

Phillip Gawlowski

unread,
Dec 30, 2009, 9:35:43 PM12/30/09
to
On 31.12.2009 03:24, Albert Schlef wrote:
> (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.

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 `<main>'
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.

--
Phillip Gawlowski

Jörg W Mittag

unread,
Dec 30, 2009, 9:38:04 PM12/30/09
to
Albert Schlef 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

Seebs

unread,
Dec 30, 2009, 9:43:53 PM12/30/09
to
On 2009-12-31, Phillip Gawlowski <p...@thimian.com> 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
--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

David Masover

unread,
Dec 30, 2009, 10:12:17 PM12/30/09
to
On Wednesday 30 December 2009 08:35:43 pm Phillip Gawlowski wrote:
> On 31.12.2009 03:24, Albert Schlef wrote:
> > (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.
>
> 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 `<main>'
> 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 `<main>'
irb(main):003:0> (nil or 4)
=> 4
irb(main):004:0> puts((nil or 4))
4
=> nil
irb(main):005:0>


Gary Wright

unread,
Dec 30, 2009, 10:33:04 PM12/30/09
to

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

> (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.

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

botp

unread,
Dec 30, 2009, 10:36:56 PM12/30/09
to
On Thu, Dec 31, 2009 at 10:24 AM, Albert Schlef <albert...@gmail.com> 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

Albert Schlef

unread,
Dec 31, 2009, 12:24:12 AM12/31/09
to
Gary Wright wrote:
> On Dec 30, 2009, at 9:24 PM, Albert Schlef 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.

Albert Schlef

unread,
Dec 31, 2009, 12:32:42 AM12/31/09
to
botp wrote:
> On Thu, Dec 31, 2009 at 10:24 AM, Albert Schlef <albert...@gmail.com>
> 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.

Albert Schlef

unread,
Dec 31, 2009, 12:39:28 AM12/31/09
to
Albert Schlef 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

unread,
Dec 31, 2009, 12:29:53 AM12/31/09
to
On 2009-12-31, Albert Schlef <albert...@gmail.com> 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.

Albert Schlef

unread,
Dec 31, 2009, 1:16:22 AM12/31/09
to
Seebs wrote:
> On 2009-12-31, Albert Schlef <albert...@gmail.com> 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)

Phillip Gawlowski

unread,
Dec 31, 2009, 1:43:28 AM12/31/09
to
On 31.12.2009 06:32, Albert Schlef 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. :)

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

--
Phillip Gawlowski

Jeff Peng

unread,
Dec 31, 2009, 2:13:13 AM12/31/09
to
botp :

> On Thu, Dec 31, 2009 at 10:24 AM, Albert Schlef <albert...@gmail.com> 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..
>

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 `<main>'

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.

Seebs

unread,
Dec 31, 2009, 3:22:33 AM12/31/09
to

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 ().

Albert Schlef

unread,
Dec 31, 2009, 4:31:39 AM12/31/09
to
Seebs wrote:
> On 2009-12-31, Albert Schlef <albert...@gmail.com> 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)

Phillip Gawlowski

unread,
Dec 31, 2009, 4:35:43 AM12/31/09
to
On 31.12.2009 10:31, Albert Schlef 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 Gawlowski

Albert Schlef

unread,
Dec 31, 2009, 4:44:58 AM12/31/09
to
Seebs wrote:
> On 2009-12-31, Albert Schlef <albert...@gmail.com> 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,
e` would fail, because it'd mean `(do_this() or a), c = d, e`.

Albert Schlef

unread,
Dec 31, 2009, 4:51:09 AM12/31/09
to
Phillip Gawlowski wrote:
> On 31.12.2009 10:31, Albert Schlef 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 Schlef

unread,
Dec 31, 2009, 4:54:05 AM12/31/09
to
Albert Schlef 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."

Marnen Laibow-Koser

unread,
Dec 31, 2009, 4:59:29 AM12/31/09
to

Just use Ruby's rescue syntax instead of trying to be clever.

Best,
--
Marnen Laibow-Koser
http://www.marnen.org
mar...@marnen.org

Phillip Gawlowski

unread,
Dec 31, 2009, 5:02:31 AM12/31/09
to
On 31.12.2009 10:51, Albert Schlef wrote:

> 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)"?

Note: I'm dumbing this down as much as I can (from my limited
understanding of Ruby internals), so no offense if I treat you like a
child, that's not my intention, and serves to make the issue
understandable. :)

Since it's an if statement, you probably can. In this case, since 123 is
always true, Ruby can "ignore" the "if true" bit (kinda, sorta).

> In other words, why can I do this:
>
> puts 999
>
> But I *can't* do this:
>
> puts (123 if true)

Because puts takes an argument, not a statement (basically).

The problem with computers is that they are stupid. It is obvious, to
you, that you *mean* "output 123, if 123 is true". However, Ruby cannot
understand intent.
It sees "output (123 if true). Wait, I can't handle that, let me tell
the smart guy about that, so that he can explain it really slow for me."

This is an effect of multiple issues: Precedence, optimizations done by
the interpreter (compiler, if you want), and the conflict of statement
vs expression ("if" is a statement, "123 if true" is an expression for
the purpose of this explanation).

So, in a nutshell: Ruby throws up its arms, because it cannot understand
what you want.

That's why "puts 123 if true", "(puts 123) if true" both work, but "puts
(123 if true)" doesn't.

Kinda.

--
Phillip Gawlowski

Albert Schlef

unread,
Dec 31, 2009, 5:35:18 AM12/31/09
to
Phillip Gawlowski wrote:
> On 31.12.2009 10:51, Albert Schlef wrote:
>> In other words, why can I do this:
>>
>> puts 999
>>
>> But I *can't* do this:
>>
>> puts (123 if true)
>
> Because puts takes an argument, not a statement (basically).

Then why can I do this?

puts (123 or true)

Are you going to tell me that "123 or true", unlike "123 if true",
*isn't* a statement?

If "123 or true" isn't a statement, then it's a simple expression. And
then I would be able to do:

puts(123 or true) # Note: no space before parentheses

But I can't! So it follows that "123 or true" too is a statement.

Let me sum it up:

puts (123 if true) # Syntax error.

puts (123 or true) # Works.

Although both are "statements".

>
> The problem with computers is that they are stupid. It is obvious, to
> you, that you *mean* "output 123, if 123 is true".

No, no, no. By `puts (123 if true)` I mean: output the result of `123 if
true`.

Albert Schlef

unread,
Dec 31, 2009, 5:38:33 AM12/31/09
to
Marnen Laibow-Koser wrote:
> Albert Schlef wrote:
>> Albert Schlef wrote:
>>
>> 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.
>
> Just use Ruby's rescue syntax instead of trying to be clever.

What do you mean?

Phillip Gawlowski

unread,
Dec 31, 2009, 5:53:13 AM12/31/09
to
On 31.12.2009 11:35, Albert Schlef wrote:
> Then why can I do this?
>
> puts (123 or true)
>
> Are you going to tell me that "123 or true", unlike "123 if true",
> *isn't* a statement?

I'm afraid I am. It's an evaluation. Boolean evaluation (with "and" /
"or" having lower precedence than && / ||).

> If "123 or true" isn't a statement, then it's a simple expression. And
> then I would be able to do:

Take a third option: It's an evaluation. ;)


Crash course in Boolean logic:

We have two items A and B.

Case "AND":
return true if, and only if, both "a" *and* "b" are true.

Example:
irb(main):004:0> a, b = true, true
=> [true, true]
irb(main):005:0> a and b
=> true
irb(main):006:0> b = false
=> false
irb(main):007:0> a and b
=> false
irb(main):008:0>

As you see, the evaluation spits back a result: True, if both "a" and
"b" are true, false if only "a" or "b" is true.

Case "OR":
return true if *either* "a" *or* "b" are true

Example:
irb(main):008:0> a, b = false, false
=> [false, false]
irb(main):009:0> a or b
=> false
irb(main):010:0> a = true
=> true
irb(main):011:0> a or b
=> true
irb(main):012:0> b = false
=> false
irb(main):013:0> a or b
=> true

As you can see, if both "a" and "b" are false, the evaluation returns
false ("returns false" meaning "the result is false").
If either "a" *or* "b" are true, the evaluation returns true.
Same if both "a" *and* "b" are true.

> No, no, no. By `puts (123 if true)` I mean: output the result of `123 if
> true`.

That's what I said, I was just verbose about it. ;)

--
Phillip Gawlowski

Robert Klemme

unread,
Dec 31, 2009, 6:04:23 AM12/31/09
to

And you can even omit the method brackets as in

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

Kind regards

robert

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/

Phillip Gawlowski

unread,
Dec 31, 2009, 6:06:27 AM12/31/09
to
On 31.12.2009 11:38, Albert Schlef wrote:

> What do you mean?

Something like this:


PS C:\Scripts> ruby .\unless.rb

we had an argument error


PS C:\Scripts> ruby .\unless.rb arg
arg
PS C:\Scripts> cat .\unless.rb

begin
raise ArgumentError unless ARGV[0]
puts ARGV[0]
rescue ArgumentError
puts "we had an argument error"
end

Basically, the begin/rescue/end tokens (bits that Ruby understands
without being told about by you) allow the programmer to recover from an
error in a graceful way.

If you had a file open, for example, you can make sure it is closed
properly if a so-called exception (Like ArgumentError in the example)
appears.

--
Phillip Gawlowski

Bertram Scharpf

unread,
Dec 31, 2009, 9:15:14 AM12/31/09
to
Hi,

Am Donnerstag, 31. Dez 2009, 11:24:26 +0900 schrieb Albert Schlef:
> (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.

There's a difference between _grouping_ parentheses (like
begin...end) and _method_ _call_ parentheses:

puts (nil or 4) # vs.
puts( nil or 4)

See:

irb(main):001:0> $-w = true
=> true
irb(main):002:0> puts( nil or 4)
SyntaxError: compile error
(irb):2: syntax error, unexpected kOR, expecting ')'
puts( nil or 4)
^
from (irb):2
irb(main):003:0> puts (nil or 4)
(irb):3: warning: (...) interpreted as grouped expression
4
=> nil


Bertram


--
Bertram Scharpf
Stuttgart, Deutschland/Germany
*
Support `String#notempty?': <http://raa.ruby-lang.org/project/step>.

Seebs

unread,
Dec 31, 2009, 11:35:48 AM12/31/09
to
On 2009-12-31, Albert Schlef <albert...@gmail.com> wrote:
> so doens't this mean that wherever I can put "999" I can also put "(123
> if true)"?

Apparently not.

Marnen Laibow-Koser

unread,
Dec 31, 2009, 12:25:37 PM12/31/09
to
Albert Schlef wrote:
> Marnen Laibow-Koser wrote:
>> Albert Schlef wrote:
>>> Albert Schlef wrote:
>>>
>>> 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.
>>
>> Just use Ruby's rescue syntax instead of trying to be clever.
>
> What do you mean?

begin

rescue

end

Look it up.

Or is that not what you didn't understand?

Best,
--
Marnen Laibow-Koser
http://www.marnen.org
mar...@marnen.org

Charles Oliver Nutter

unread,
Dec 31, 2009, 7:40:59 PM12/31/09
to
2009/12/30 Jörg W Mittag <JoergWMi...@googlemail.com>:
> Albert Schlef 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).

We do not all use the same parser. At the very least, they're all
written in our local language. We use parsers that were originally
ports of the original parser, and while changing over the years still
match MRI's parser behavior.

If MRI and YARV do it, then we do it because that's what MRI and YARV do.

Minor nitpick :)

- Charlie

Charles Oliver Nutter

unread,
Dec 31, 2009, 7:47:53 PM12/31/09
to
On Wed, Dec 30, 2009 at 11:32 PM, Albert Schlef <albert...@gmail.com> 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")

First off, I'd say that this is probably confusing form to use. If I
ever saw this in code I'd write it differently.

> 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.

This isn't too bad, for what you want:

some_func ARGV[0] || raise('you must provide an argument')

or:

some_func(ARGV[0] || raise('you must provide an argument')

And if I were to write this, I'd probably choose one of these variants:

ARGV[0] ? some_func(ARGV[0]) : raise 'you must provide an argument'

or

raise 'you must provide an argument' unless ARGV[0]
some_func(ARGV[0])

- Charlie

Albert Schlef

unread,
Jan 1, 2010, 2:23:36 AM1/1/10
to
Bertram Scharpf wrote:
[...]

> See:
>
> irb(main):001:0> $-w = true
[...]

> irb(main):003:0> puts (nil or 4)
> (irb):3: warning: (...) interpreted as grouped expression
> 4

Thanks, I didn't know of this $-w trick.

Albert Schlef

unread,
Jan 1, 2010, 2:30:19 AM1/1/10
to
Phillip Gawlowski wrote:
> begin
> raise ArgumentError unless ARGV[0]
> puts ARGV[0]
> rescue ArgumentError
> puts "we had an argument error"
> end
>
> Basically, the begin/rescue/end tokens (bits that Ruby understands
> [...]

Thanks Phillip (and Charles Nutter) for all your help. In my 'raise' I
tried to mimic Perl's "or die" idiom. But I see that your example is
more elegant.


> > If "123 or true" isn't a statement, then it's a simple expression. And
> > then I would be able to do:
>
> Take a third option: It's an evaluation. ;)

For the time being I'll take the fourth option: The Ruby grammar is
weird in some corners, and we just have to accept it.

Phillip Gawlowski

unread,
Jan 1, 2010, 2:38:31 AM1/1/10
to
On 01.01.2010 08:30, Albert Schlef wrote:

> Thanks Phillip (and Charles Nutter) for all your help. In my 'raise' I
> tried to mimic Perl's "or die" idiom. But I see that your example is
> more elegant.

Thank you. :)

However, my example is a plain by-the-books example of how Ruby does
exceptions.

So, thank Matz for creating something elegant in the first place. :)

> For the time being I'll take the fourth option: The Ruby grammar is
> weird in some corners, and we just have to accept it.

It is indeed. The more complex your desires get, the weirder Ruby gets,
IME. Overall, though, it's pretty clean and simple to use, and keeps
weirdness to the edge cases.

That's why I prefer a more verbose, explicit style of programming in
Ruby: It makes it clear to me what I attempt, and thus, hopefully,
Ruby's parser doesn't throw a wrench in my machinations. ;)

--
Phillip Gawlowski

David A. Black

unread,
Jan 1, 2010, 6:09:17 AM1/1/10
to
Hi --

On Thu, 31 Dec 2009, Phillip Gawlowski wrote:

> On 31.12.2009 11:35, Albert Schlef wrote:
>> Then why can I do this?
>>
>> puts (123 or true)
>>
>> Are you going to tell me that "123 or true", unlike "123 if true",
>> *isn't* a statement?
>
> I'm afraid I am. It's an evaluation. Boolean evaluation (with "and" / "or"
> having lower precedence than && / ||).
>
>> If "123 or true" isn't a statement, then it's a simple expression. And
>> then I would be able to do:
>
> Take a third option: It's an evaluation. ;)

Everything evaluates to something (an object) though. Evaluation is
more a process than a special kind of syntactic construct.

>> No, no, no. By `puts (123 if true)` I mean: output the result of `123 if
>> true`.
>
> That's what I said, I was just verbose about it. ;)

I think you said:

> It is obvious, to you, that you *mean* "output 123, if 123 is true".

The code doesn't test for the truth value of 123.


David

--
David A. Black
Senior Developer, Cyrus Innovation Inc.
THE COMPLEAT RUBYIST, Ruby training with Black/Brown/McAnally!
January 22-23, Tampa, Florida
Info and registration at http://www.thecompleatrubyist.com

David A. Black

unread,
Jan 1, 2010, 6:15:03 AM1/1/10
to
Hi --

On Thu, 31 Dec 2009, Phillip Gawlowski wrote:

> On 31.12.2009 06:32, Albert Schlef 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. :)
>
> Works in 1.8.6 and 1.9.1, too, to my great relief.

It even works in 1.0:

$ ruby10 -ve 'raise "Argument error" unless ARGV[0]'
ruby - version 1.0-971225 (i686-linux)
-e:1: RuntimeError: Argument error

I wouldn't worry about that idiom ceasing to work :-)

David A. Black

unread,
Jan 1, 2010, 6:20:04 AM1/1/10
to
Hi --

On Thu, 31 Dec 2009, Albert Schlef 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.

It's not supposed to; it's supposed to read as Ruby :-) I wouldn't
make too much of the English-likeness. I think of it more as an
emergent thing than as a style guideline.

Phillip Gawlowski

unread,
Jan 1, 2010, 6:25:33 AM1/1/10
to
On 01.01.2010 12:15, David A. Black wrote:

> I wouldn't worry about that idiom ceasing to work :-)

In open source software (or Free Software), I *do* worry about API
stability, or rather compatibility of version X to version Y.

I've been burned by Linux kernel changes far too often to *not* worry. :(

Mind, I'm not averse to change, even change that sheds weight and thus
breaks backwards compatibility, but I prefer it to be in a major
release, rather than a minor version.

Very different issue from the OP, though.

--
Phillip Gawlowski

David A. Black

unread,
Jan 1, 2010, 6:29:40 AM1/1/10
to
Hi --

On Fri, 1 Jan 2010, Phillip Gawlowski wrote:

> On 01.01.2010 12:15, David A. Black wrote:
>
>> I wouldn't worry about that idiom ceasing to work :-)
>
> In open source software (or Free Software), I *do* worry about API stability,
> or rather compatibility of version X to version Y.

So do I, but I think we're safe on this particular one. That's all I
mean.

botp

unread,
Jan 1, 2010, 7:30:03 AM1/1/10
to
On Thu, Dec 31, 2009 at 3:13 PM, Jeff Peng <jeff...@netzero.net> wrote:
> I know Perl, but I'm still surprised.
>
> # perl -le 'print undef or 4'
>
> # perl -le 'print(undef or 4)'
> 4

do not be surprise, ruby opted for the former case since it is more
common, and therefore has relegated the "or/and" ops w very low
precedence level (and ergo different fr their sibling ops "||/&&")

in other words, if you see a method like

>> puts 1,2 or 4
1
2
=> 4

it actually means

>> puts( 1,2) or 4
1
2
=> 4

and if you write a statement like

>> puts( 1,2 or 4)

ruby will err for you
but friendly enough to allow you to by (re)emphasizing...

so maybe you meant

>> puts( 1, (2 or 4))


best regards
-botp

0 new messages