Why can't I use "or" here?

Seebs wrote:

···

On 2009-12-31, Albert Schlef <albertschlef@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)
--
Posted via http://www.ruby-forum.com/\.

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

···

On 2009-12-31, Albert Schlef <albertschlef@gmail.com> wrote:

--
Posted via http://www.ruby-forum.com/\.

Albert Schlef wrote:

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.

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

Best,

···

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

--
Posted via http://www.ruby-forum.com/\.

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

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 :slight_smile:

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

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

···

On 2009-12-31, Albert Schlef <albertschlef@gmail.com> wrote:

Interesting.

Why is the following a syntax error?

  puts (123 if true)

and the following isn't?

  puts (123 or 456)

--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
| Seebs.Net <-- lawsuits, religion, and funny pictures
Fair game (Scientology) - Wikipedia <-- get educated!

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

···

--
Posted via http://www.ruby-forum.com/\.

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?

···

--
Posted via http://www.ruby-forum.com/\.

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

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.

···

On 01.01.2010 12:15, David A. Black wrote:

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

--
Phillip Gawlowski

Seebs wrote:

···

On 2009-12-31, Albert Schlef <albertschlef@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)
--
Posted via http://www.ruby-forum.com/\.

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.

···

On 31.12.2009 11:38, Albert Schlef wrote:

What do you mean?

--
Phillip Gawlowski

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
marnen@marnen.org
--
Posted via http://www.ruby-forum.com/\.

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 :slight_smile:

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.

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

Because here you do an assignment.

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

···

On 31.12.2009 10:31, Albert Schlef wrote:

Then why does the following work?

    a = (123 if true)

--
Phillip Gawlowski

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

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.

···

--
Posted via http://www.ruby-forum.com/\.

Phillip Gawlowski 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)

???

···

On 31.12.2009 10:31, Albert Schlef wrote:

--
Posted via http://www.ruby-forum.com/\.

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

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

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

···

On 01.01.2010 08:30, Albert Schlef wrote:

--
Phillip Gawlowski

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

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.

···

On 31.12.2009 10:51, Albert Schlef wrote:

--
Phillip Gawlowski

Apparently not.

-s

···

On 2009-12-31, Albert Schlef <albertschlef@gmail.com> wrote:

so doens't this mean that wherever I can put "999" I can also put "(123
if true)"?

--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
| Seebs.Net <-- lawsuits, religion, and funny pictures
Fair game (Scientology) - Wikipedia <-- get educated!

Phillip Gawlowski 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`.

···

On 31.12.2009 10:51, Albert Schlef wrote:

--
Posted via http://www.ruby-forum.com/\.

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

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

···

On 31.12.2009 11:35, Albert Schlef wrote:

--
Phillip Gawlowski