Jump to page: 1 2
Thread overview
Evaluation Order
May 29, 2004
Sean Kelly
May 29, 2004
Andy Friesen
May 29, 2004
Sean Kelly
May 29, 2004
Bent Rasmussen
May 29, 2004
Sean Kelly
May 30, 2004
Walter
May 30, 2004
Arcane Jill
May 30, 2004
Walter
May 30, 2004
Juan C
May 30, 2004
Walter
May 30, 2004
Kevin Bealer
May 30, 2004
Vathix
May 30, 2004
Juan c
May 31, 2004
Kevin Bealer
May 30, 2004
J Anderson
May 29, 2004
This bit from the spec has me concerned:

>Unless otherwise specified, the implementation is free to evaluate the >components of an expression in any order. It is an error to depend on >order of evaluation when it is not specified.
	
C++ has well-defined evaluation rules, and this almost seems necessary for complex mathematical expressions.  But aside from logical operators and the comma operator I can't find any information on eevaluation order in the D spec.  For example, this expression:

int x = 5 * 4 / 3;

has a well-defined result in C/C++, but does it in D?  Or should perenthesis always be used?

Sean
May 29, 2004
Sean Kelly wrote:
> This bit from the spec has me concerned:
> 
>  >Unless otherwise specified, the implementation is free to evaluate the  >components of an expression in any order. It is an error to depend on  >order of evaluation when it is not specified.
>     C++ has well-defined evaluation rules, and this almost seems necessary for complex mathematical expressions.  But aside from logical operators and the comma operator I can't find any information on eevaluation order in the D spec.  For example, this expression:
> 
> int x = 5 * 4 / 3;
> 
> has a well-defined result in C/C++, but does it in D?  Or should perenthesis always be used?

The result is well defined, but the order in which the terms are evaluated is not.  That part of the spec pertains to something like this:

int x = (5 * 4) + (3 / 2);

D reserves the right to compute either the multiply or divide first. Obviously, since the addition needs the result of both, it is going to be last.

 -- andy
May 29, 2004
Andy Friesen wrote:
>
> The result is well defined, but the order in which the terms are evaluated is not.  That part of the spec pertains to something like this:
> 
> int x = (5 * 4) + (3 / 2);
> 
> D reserves the right to compute either the multiply or divide first. Obviously, since the addition needs the result of both, it is going to be last.

Ah, that's what I figured but the attached examples had me wondering. So D follows standard operator precedence rules and evaluation order for all scenarios I care about :)

Sean
May 29, 2004
I'd guess this has something to do with side-effects. If you have a boolean expression like

a || b

and both sides exhibit side-effects, you can't rely on any order of evaluation to determine which side-effect takes place first. Perhaps you can't even be sure that both sides of the above expression will be evaluated if any of the sides evaluate to true. I don't know though.

The specification has an example where the order of evaluation affects the value of the expression

    c = a + (a = b)

So here the order of evaluation affects c which it would seem easy for the compiler to detect. Of course its easy to construct difficult cases.

In such a simple example it would seem no problem to detect order of evaluation dependency but of course its easy to construct an example where its much harder to detect that evaluation order affects the result. It seems like a good principle for stuff like assertions that use boolean expressions.

Further examination of the spec says

"The OrOr expression evaluates its left operand. If the left operand, converted to type bool, evaluates to true, then the right operand is not evaluated."

It makes sense and of course if you expected the right operand to evaluate because it exhibits some side-effect then you'll be disappointed and that's how it should be it seems to me. I think Eiffel has allways evaluates the full boolean expression except if you use "and then" or "or else".


May 29, 2004
Bent Rasmussen wrote:

> I'd guess this has something to do with side-effects. If you have a boolean
> expression like
> 
> a || b
> 
> and both sides exhibit side-effects, you can't rely on any order of
> evaluation to determine which side-effect takes place first. Perhaps you
> can't even be sure that both sides of the above expression will be evaluated
> if any of the sides evaluate to true. I don't know though.

That was my guess too, but "expressions" was sufficiently vage that I wanted to ask.

> The specification has an example where the order of evaluation affects the
> value of the expression
> 
>     c = a + (a = b)

This is the example that threw me.  I had thought that the parenthesis would force the assignment to occur before the addition, even though assignments are typically fairly low on the precedence tree.

> Further examination of the spec says
> 
> "The OrOr expression evaluates its left operand. If the left operand,
> converted to type bool, evaluates to true, then the right operand is not
> evaluated."

This is required for short-circuit evaluation.  The AndAnd bit has a similar clause.  But they're just about the only expressions that mention evaluation, so I was left wondering.  (for the record, the comma operator and the logical if operators also mention evaluation order).

> It makes sense and of course if you expected the right operand to evaluate
> because it exhibits some side-effect then you'll be disappointed and that's
> how it should be it seems to me. I think Eiffel has allways evaluates the
> full boolean expression except if you use "and then" or "or else".

Yup.  Some of the .NET languages are like this also.  Frankly, it drives me crazy :)  I guess I've just become accustomed to the C/C++ method.

Sean
May 30, 2004
"Sean Kelly" <sean@f4.ca> wrote in message news:c9ase5$a2c$1@digitaldaemon.com...
> This bit from the spec has me concerned:
>
>  >Unless otherwise specified, the implementation is free to evaluate the
>  >components of an expression in any order. It is an error to depend on
>  >order of evaluation when it is not specified.
>
> C++ has well-defined evaluation rules, and this almost seems necessary for complex mathematical expressions.  But aside from logical operators and the comma operator I can't find any information on eevaluation order in the D spec.  For example, this expression:
>
> int x = 5 * 4 / 3;
>
> has a well-defined result in C/C++, but does it in D?  Or should perenthesis always be used?

There are two different things going on here - one is evaluation order, and the other is the operator precedence, associativity and commutativity rules. The latter are well defined, in D as well as C++, and in your example evaluates as (5*4)/3. The former are not, in D and C++. For example:

    (a + b) * (c + d)

which is evaluated first, (a + b) or (c + d)? The specification leaves this
up to the compiler in both languages.


May 30, 2004
In article <c9blde$1bs0$3@digitaldaemon.com>, Walter says...

>There are two different things going on here - one is evaluation order, and the other is the operator precedence, associativity and commutativity rules. The latter are well defined, in D as well as C++,

Is precedence order defined the same way in D that it is in C?

I ask because I think C got it wrong, and I'd hate to think we were copying the flaws as well as the good bits.

I always thought it a mistake that the precedence of &, | and ^ was defined such that:

>       if (a & 1 == 1)

gives (1 == 1) precedence over (a & 1). It's not intuitive in C. C++ copied it, and it's not intuitive in C++. I think even Java copied it, and it's not intuitive there either. Believe it or not, I think BASIC got this right!

I would prefer precedence order to be:

<< >>
& ^ |
* / %
+ -
< > <= >= etc
== !=
&& ||

(but I guess it would break too much to change that now).

Arcane Jill


May 30, 2004
"Arcane Jill" <Arcane_member@pathlink.com> wrote in message news:c9bssf$1mld$1@digitaldaemon.com...
> In article <c9blde$1bs0$3@digitaldaemon.com>, Walter says...
> >There are two different things going on here - one is evaluation order,
and
> >the other is the operator precedence, associativity and commutativity
rules.
> >The latter are well defined, in D as well as C++,
> Is precedence order defined the same way in D that it is in C?

Yes.

> I ask because I think C got it wrong, and I'd hate to think we were
copying the
> flaws as well as the good bits.
>
> I always thought it a mistake that the precedence of &, | and ^ was
defined such
> that:
>
> >       if (a & 1 == 1)
>
> gives (1 == 1) precedence over (a & 1). It's not intuitive in C. C++
copied it,
> and it's not intuitive in C++. I think even Java copied it, and it's not intuitive there either. Believe it or not, I think BASIC got this right!
>
> I would prefer precedence order to be:
>
> << >>
> & ^ |
> * / %
> + -
> < > <= >= etc
> == !=
> && ||
>
> (but I guess it would break too much to change that now).

Since D is designed to appeal to C/C++ programmers, changing the precedence order that, for good or ill, we're all used to would introduce subtle bugs. I'd prefer to change only things that would yield obvious errors if done using the C/C++ semantics.


May 30, 2004
In article <c9bssf$1mld$1@digitaldaemon.com>, Arcane Jill says...
>
>In article <c9blde$1bs0$3@digitaldaemon.com>, Walter says...
>
>>There are two different things going on here - one is evaluation order, and the other is the operator precedence, associativity and commutativity rules. The latter are well defined, in D as well as C++,
>
>Is precedence order defined the same way in D that it is in C?
>
>I ask because I think C got it wrong, and I'd hate to think we were copying the flaws as well as the good bits.
>
>I always thought it a mistake that the precedence of &, | and ^ was defined such that:
>
>>       if (a & 1 == 1)
>
>gives (1 == 1) precedence over (a & 1). It's not intuitive in C. C++ copied it, and it's not intuitive in C++. I think even Java copied it, and it's not intuitive there either. Believe it or not, I think BASIC got this right!
>
>I would prefer precedence order to be:
>
><< >>
>& ^ |
>* / %
>+ -
>< > <= >= etc
>== !=
>&& ||
>
>(but I guess it would break too much to change that now).
>
>Arcane Jill

I remember that "*" is before "+", comparisons (<, ==) are before "&&" and "||", and maybe one or two others.  For almost everything else I use the parens, for readability and safety.  I don't expect the compiler to get it wrong, but I know that I will, and I hate debugging this stuff: I'd rather be hunting orc than squirrel if you get my meaning.

Incidentally, what are "&&" and "||" supposed to return?  I think at one point I read that || returns the first argument that is true, or the second argument, but I tried it and it didn't work in whatever language I was using.  It would be useful if you could say: (return x || y || 100), but I don't know if that makes sense in the bigger picture.

Kevin



May 30, 2004
"Kevin Bealer" <Kevin_member@pathlink.com> wrote in message
news:c9c6uu$24ul$1@digitaldaemon.com...
   ...
> Incidentally, what are "&&" and "||" supposed to return?  I think at one
point I
> read that || returns the first argument that is true, or the second
argument,
> but I tried it and it didn't work in whatever language I was using.  It
would be
> useful if you could say: (return x || y || 100), but I don't know if that
makes
> sense in the bigger picture.
>

JavaScript does that with ||, like alert("foo" || "bar"); displays "foo". I've never used it in real code, but it is interesting. C style languages just return 0 for false and 1 for true; which is depended on in some cases. Changing it would cause those "subtle bugs" I would think.


« First   ‹ Prev
1 2