Order of evaluation and precedence

In The Ruby P.ming Language, it is asserted that order of
evaluation
is controlled by precedence.

However, this is often asserted in books about C, where it’s definitely
not true. Is it actually true in Ruby?

In other words:

def a
puts “a”
1
end
def b
puts “b”
1
end
def c
puts “c”
1
end
x = a + (b + c)

Is it actually guaranteed that the output will have “a” after “b” and
“c”?
In C, it wouldn’t be. (Compilers are free to evaluate the operands in
any
order whatsoever, then feed them into operators, all that precedence and
grouping controls is which operands go to which operators.)

-s

Hi,

In message “Re: Order of evaluation and precedence”
on Sun, 22 Nov 2009 07:30:12 +0900, Seebs [email protected]
writes:

|Is it actually guaranteed that the output will have “a” after “b” and “c”?
|In C, it wouldn’t be.

In Ruby, it should be. It’s part of spec.

          matz.

On Nov 21, 5:50 pm, Yukihiro M. [email protected] wrote:

                                                    matz.

Well if that’s the case:

irb(main):018:0> def a; puts “a”; 1 end; def b; puts “b”; 1 end; def
c; puts “c”; 1 end
=> nil
irb(main):019:0> a + (b + c)
a
b
c
=> 3
irb(main):020:0> RUBY_VERSION
=> “1.8.7”
irb(main):021:0> exit
xeno@Clover:~/projects/rss_ish$ ruby -v
ruby 1.8.7 (2009-06-12 patchlevel 174) [x86_64-linux]

I had always assumed that methods were always evaluated left to right,
order of operations having no impact on that. But if this isn’t
supposed to be the case, is it a bug? Or am I misunderstanding the
issue?

On 2009-11-21, Yukihiro M. [email protected] wrote:

In message “Re: Order of evaluation and precedence”
on Sun, 22 Nov 2009 07:30:12 +0900, Seebs [email protected] writes:
|Is it actually guaranteed that the output will have “a” after “b” and “c”?
|In C, it wouldn’t be.

In Ruby, it should be. It’s part of spec.

Okay, thanks! I just couldn’t tell whether it was an intentional part
of
the spec, or just the usual ambiguity that crops up when people discuss
precedence and order of evaluation.

(In C, I think it’s a feature that order of evaluation isn’t defined;
in Ruby, I think it’s probably a feature that it is.)

-s

On Sat, Nov 21, 2009 at 5:30 PM, Seebs [email protected] wrote:

     1

Is it actually guaranteed that the output will have “a” after “b” and “c”?
In C, it wouldn’t be. (Compilers are free to evaluate the operands in any
order whatsoever, then feed them into operators, all that precedence and
grouping controls is which operands go to which operators.)

I think you are confusing precedence ordering with evaluation strategy.

Precedence determines the order in which the
operators/functions/methods are performed. so in

a + b * c

the * is performed before the +

But the timing of when the argument expressions is evaiuated is a
different issue.

Ruby like most other languages uses what is called applicative
ordering, which means that the arguments to a function are evaluated
before the function is called (or applied). They don’t need to be
evaluated JUST before the function is applied, just BEFORE it is.

Consider this Ruby program and its output:

class NoisyNum

def initialize(name)
@name = name
puts “#{name} created”
end

def to_s
@name.to_s
end

def +(other)
NoisyNum.new(“#{self}+#{other}”)
end

def (other)
NoisyNum.new("#{self}
#{other}")
end

end

def N(name)
NoisyNum.new(name)
end

x = N(:a) + N(:b) * N(:c)

a created
b created
c created
bc created
a+b
c created

A few languages use what is called Normal order (strange since it’s
not the normal strategy used) in which the evaluation of the arguments
is delayed until they are needed by a function. Some languages like
Lisp/Scheme normally use applicative order, but have what are called
special forms which use normal order.

This allows special forms to be used to define control flow like
if/then/else to be implemented with a function with the condition, and
the two alternatives.

In Ruby you could think of the expression a || b as a special form in
that the b expression is not evaluated unless a is not truthy.

HTH


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Hi,

In message “Re: Order of evaluation and precedence”
on Sun, 22 Nov 2009 07:50:09 +0900, Yukihiro M.
[email protected] writes:

|In message “Re: Order of evaluation and precedence”
| on Sun, 22 Nov 2009 07:30:12 +0900, Seebs [email protected] writes:
|
||Is it actually guaranteed that the output will have “a” after “b” and “c”?
||In C, it wouldn’t be.
|
|In Ruby, it should be. It’s part of spec.

Oops, I have mistaken. The evaluation order should be from left to
right. So, even when you’ve put parentheses around b + c, the output
should be “a” then “b” then “c”.

          matz.

On Sat, Nov 21, 2009 at 6:42 PM, Yukihiro M. [email protected]
wrote:

|
|In Ruby, it should be. It’s part of spec.

Oops, I have mistaken. The evaluation order should be from left to
right. So, even when you’ve put parentheses around b + c, the output
should be “a” then “b” then “c”.

Hi Matz.

As I pointed out in my earlier post, even though the + within the
parentheses gets evaluated before the first +, the arguments are still
evaluated left to right.

Right?


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Hi,

In message “Re: Order of evaluation and precedence”
on Sun, 22 Nov 2009 08:46:57 +0900, Rick DeNatale
[email protected] writes:

|Hi Matz.
|
|As I pointed out in my earlier post, even though the + within the
|parentheses gets evaluated before the first +, the arguments are still
|evaluated left to right.
|
|Right?

Correct. The precedence does not effect on evaluation order.

          matz.

On 2009-11-21, Rick DeNatale [email protected] wrote:

I think you are confusing precedence ordering with evaluation strategy.

I am not.

Precedence determines the order in which the
operators/functions/methods are performed.

Right. But the book says that the expressions are evaluated in
that order…

But the timing of when the argument expressions is evaiuated is a
different issue.

The reason I asked is not that I’m generally unaware of this, but
rather, that many people believe that this means that everything inside
()
has to be performed before anything outside of (), for instance.

I was trying to figure out whether the statement that precedence affects
order of evaluation meant that it controlled the order in which
subexpressions
were evaluated, or just the grouping and ordering of operators.

Ruby like most other languages uses what is called applicative
ordering, which means that the arguments to a function are evaluated
before the function is called (or applied). They don’t need to be
evaluated JUST before the function is applied, just BEFORE it is.

Right. That was what I was expecting. But now I am confused, because
I thought I asked that and Matz said that it did control the order of
evaluation, but now I think he said it doesn’t.

Which I’m guessing means that evaluation of operators follows precedence
order
(or at least, everything looks as though it did).

-s

On 2009-11-22, David M. [email protected] wrote:

On Saturday 21 November 2009 05:25:07 pm Seebs wrote:

(In C, I think it’s a feature that order of evaluation isn’t defined;
in Ruby, I think it’s probably a feature that it is.)

I’m curious why you think each behavior is a feature…

In Ruby, the “feature” would be to make things easier to understand, POLS and
all that. While I don’t find left-to-right intuitive here, it’s certainly
intuitive that method dispatch is deterministic – I suspect it’s the same
philosophy behind making hashes preserve insertion order in 1.9.

Basically, yeah – I like the idea of having a predictable order for
evaluation as much as possible in a high level language.

In C, the only feature I can see is that some optimizations could be made,
right? I’m curious how exactly that would work, in a non-functional language
like C. I’m not doubting it could be, I just don’t know how.

Basically, compilers can generate all the code they need, then shuffle
it
around to do things like “keep these three operations together since
they will
use the same cache line” or “calculate the branch for the ternary
operator
long enough before taking it for the branch predictor to kick in”, stuff
like
that.

For instance, in a lot of implementations, function args might be
evaluated
left-to-right for most functions, but right-to-left for variadic
functions.
Weird stuff happens. :slight_smile:

-s

On Saturday 21 November 2009 05:25:07 pm Seebs wrote:

(In C, I think it’s a feature that order of evaluation isn’t defined;
in Ruby, I think it’s probably a feature that it is.)

I’m curious why you think each behavior is a feature…

In Ruby, the “feature” would be to make things easier to understand,
POLS and
all that. While I don’t find left-to-right intuitive here, it’s
certainly
intuitive that method dispatch is deterministic – I suspect it’s the
same
philosophy behind making hashes preserve insertion order in 1.9.

In C, the only feature I can see is that some optimizations could be
made,
right? I’m curious how exactly that would work, in a non-functional
language
like C. I’m not doubting it could be, I just don’t know how.