|
Archives
D Programming
D
D.gnu
digitalmars.D
digitalmars.D.bugs
digitalmars.D.dtl
digitalmars.D.dwt
digitalmars.D.announce
digitalmars.D.learn
digitalmars.D.debugger
C/C++ Programming
c++
c++.announce
c++.atl
c++.beta
c++.chat
c++.command-line
c++.dos
c++.dos.16-bits
c++.dos.32-bits
c++.idde
c++.mfc
c++.rtl
c++.stl
c++.stl.hp
c++.stl.port
c++.stl.sgi
c++.stlsoft
c++.windows
c++.windows.16-bits
c++.windows.32-bits
c++.wxwindows
digitalmars.empire
digitalmars.DMDScript
electronics
|
digitalmars.D - D and expression evaluation order.
↑ ↓ ← → Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
As we know, in C/C++ there are a lot of cases where the order of
evaluation of an expression is undefined.
i = i++;
c = a + (a = b);
func(++i, ++i);
D goes one step further by defining that any such behavior is illegal:
"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." in
http://www.digitalmars.com/d/expression.html .
That's nice, but why not go all the way, and actually define an
evaluation order for such expressions. There is nothing to lose, and it
should be easy to implement. This is what Java does. For
example, the following (which I found recently in JDT's code) is
perfectly legal Java code:
int length = array.length;
...
System.arraycopy(array, 0, array = new IFoo[length + 1], 0, length);
because Java not only defines that the argument evaluation order is left
to right, but also that the arguments are bound to parameters as they
are evaluated (and not after all are evaluated).
The little details matter a lot.
--
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
↑ ↓ ← → Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Bruno Medeiros wrote:
As we know, in C/C++ there are a lot of cases where the order of
evaluation of an expression is undefined.
i = i++;
c = a + (a = b);
func(++i, ++i);
D goes one step further by defining that any such behavior is illegal:
"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." in
http://www.digitalmars.com/d/expression.html .
Actually, if I read that right it just says that the order of evaluation
is undefined and should not be relied upon. Just like C/C++.
That's nice, but why not go all the way, and actually define an
evaluation order for such expressions. There is nothing to lose, and it
should be easy to implement. This is what Java does. For
example, the following (which I found recently in JDT's code) is
perfectly legal Java code:
int length = array.length;
...
System.arraycopy(array, 0, array = new IFoo[length + 1], 0, length);
because Java not only defines that the argument evaluation order is left
to right, but also that the arguments are bound to parameters as they
are evaluated (and not after all are evaluated).
The little details matter a lot.
Unspecified evaluation order is an optimization opportunity.
For instance, the most efficient parameter evaluation order can be
dependent on the calling convention, which is platform-dependent. For
instance on x86 and amd64 platforms the most efficient evaluation order
can very well be to evaluate right-to-left, since typical calling
conventions specify the last argument is to be pushed onto the stack
first[1]. (There are good reasons for that, mostly to do with varargs)
DMD's extern(D) (i.e. the default) calling convention and GDC's amd64
calling convention are a slight variation on that, passing some
arguments in a register if possible. It may for that reason be more
efficient to evaluate those in another order so that those registers can
be used in evaluation of other arguments.
[1] Though on amd64 the first few arguments are typically passed in
registers, and DMD by default passes one argument in a register as well,
so the stack may not be used if there are few arguments.
↑ ↓ ← → Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Frits van Bommel wrote:
Bruno Medeiros wrote:
As we know, in C/C++ there are a lot of cases where the order of
evaluation of an expression is undefined.
i = i++;
c = a + (a = b);
func(++i, ++i);
D goes one step further by defining that any such behavior is illegal:
"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." in
http://www.digitalmars.com/d/expression.html .
Actually, if I read that right it just says that the order of evaluation
is undefined and should not be relied upon. Just like C/C++.
Read the paragraph ahead in the doc. In D that is considered a
language(i.e. compile) error and so the compiler can issue an error. In
C/C++ it is merely undefined program behavior, the code remains compilable.
That's nice, but why not go all the way, and actually define an
evaluation order for such expressions. There is nothing to lose, and
it should be easy to implement. This is what Java does. For
example, the following (which I found recently in JDT's code) is
perfectly legal Java code:
int length = array.length;
...
System.arraycopy(array, 0, array = new IFoo[length + 1], 0, length);
because Java not only defines that the argument evaluation order is left
to right, but also that the arguments are bound to parameters as they
are evaluated (and not after all are evaluated).
The little details matter a lot.
Unspecified evaluation order is an optimization opportunity.
For instance, the most efficient parameter evaluation order can be
dependent on the calling convention, which is platform-dependent. For
instance on x86 and amd64 platforms the most efficient evaluation order
can very well be to evaluate right-to-left, since typical calling
conventions specify the last argument is to be pushed onto the stack
first[1]. (There are good reasons for that, mostly to do with varargs)
DMD's extern(D) (i.e. the default) calling convention and GDC's amd64
calling convention are a slight variation on that, passing some
arguments in a register if possible. It may for that reason be more
efficient to evaluate those in another order so that those registers can
be used in evaluation of other arguments.
In that case, it is possible for the compiler to detect if the
evaluation order matters, and if it doesn't (currently the only allowed
situation in D), it can push the arguments in any order it pleases him.
Even if that wasn't possible, I'm not sure that with modern CPU
technology, right-to-left calling conventions (last argument on top)
would be any slower to call with an left-to-right eval order, than with
an undefined order. Then again, I'm no Assembler or CPU optimization
expert, so correct if I'm wrong.
--
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
↑ ↓ ← → =?UTF-8?B?THXDrXMgTWFycXVlcw==?= <luismarques+spam gmail.com> writes:
Bruno Medeiros wrote:
In that case, it is possible for the compiler to detect if the
evaluation order matters, and if it doesn't (currently the only allowed
situation in D), it can push the arguments in any order it pleases him.
The compiler can only detect some cases, kind of like constant folding,
but it might aliviate many cases. Inter-module flow analysis would help
here (coming soon with GCC, weee!)
--
LuĂs
↑ ↓ ← → Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Bruno Medeiros wrote:
Frits van Bommel wrote:
Bruno Medeiros wrote:
As we know, in C/C++ there are a lot of cases where the order of
evaluation of an expression is undefined.
i = i++;
c = a + (a = b);
func(++i, ++i);
D goes one step further by defining that any such behavior is illegal:
"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." in
http://www.digitalmars.com/d/expression.html .
Actually, if I read that right it just says that the order of
evaluation is undefined and should not be relied upon. Just like C/C++.
Read the paragraph ahead in the doc. In D that is considered a
language(i.e. compile) error and so the compiler can issue an error. In
C/C++ it is merely undefined program behavior, the code remains compilable.
IIRC[1] the C++ standard includes "causes a compile error" as one of the
possible consequences of undefined behavior. I'm not sure about C.
[1] I've been staying away from C++ since I started using D, so this is
by no means a given...
[snip]
Unspecified evaluation order is an optimization opportunity.
For instance, the most efficient parameter evaluation order can be
dependent on the calling convention, which is platform-dependent. For
instance on x86 and amd64 platforms the most efficient evaluation
order can very well be to evaluate right-to-left, since typical
calling conventions specify the last argument is to be pushed onto the
stack first[1]. (There are good reasons for that, mostly to do with
varargs)
In that case, it is possible for the compiler to detect if the
evaluation order matters, and if it doesn't (currently the only allowed
situation in D), it can push the arguments in any order it pleases him.
<nitpick> Actually, if you check the spec it says the compiler is
allowed to issue an error if it detects the _result_ of the expression
depends on evaluation order. It doesn't seem to mention side-effects at
all, so evaluation order is technically allowed to matter (though it's
still an error to _depend_ on it). Well, unless you count side-effects
as part of the "result" of an expression... </nitpick>
Even if that wasn't possible, I'm not sure that with modern CPU
technology, right-to-left calling conventions (last argument on top)
would be any slower to call with an left-to-right eval order, than with
an undefined order. Then again, I'm no Assembler or CPU optimization
expert, so correct if I'm wrong.
Nor am I, but I've inspected a lot of the assembly code generated for my
programs and often the DMD and GDC optimizers apparently decided to
evaluate (roughly) right-to-left...
↑ ↓ ← → Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Frits van Bommel wrote:
Bruno Medeiros wrote:
Frits van Bommel wrote:
Bruno Medeiros wrote:
As we know, in C/C++ there are a lot of cases where the order of
evaluation of an expression is undefined.
i = i++;
c = a + (a = b);
func(++i, ++i);
D goes one step further by defining that any such behavior is illegal:
"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." in
http://www.digitalmars.com/d/expression.html .
Actually, if I read that right it just says that the order of
evaluation is undefined and should not be relied upon. Just like C/C++.
Read the paragraph ahead in the doc. In D that is considered a
language(i.e. compile) error and so the compiler can issue an error.
In C/C++ it is merely undefined program behavior, the code remains
compilable.
IIRC[1] the C++ standard includes "causes a compile error" as one of the
possible consequences of undefined behavior. I'm not sure about C.
[1] I've been staying away from C++ since I started using D, so this is
by no means a given...
I haven't read about C++ in detail, only C. But in both cases (and
sometimes here in the NG too) I often see the documents call "undefined
behavior" to thing they should call errors. They refer to these concepts
almost interchangeably, whereas they are not. They overlap a lot but
they are not the same, there is a subtle difference.
Dereferencing a trash pointer, for example, *is* an error. It *causes*
undefined behavior, but it *is not* merely undefined behavior: it *can
crash* your program.
On the other hand if do:
func(i++, i++);
where func simply prints prints its arguments, I will have undefined
program behavior, but no program error : that code *can not ever* crash
the program. (altough it is still likely a *conceptual* error)
This is a minor nitpick, since in practice both should be equally
avoided, but that subtle difference is still there.
[snip]
Unspecified evaluation order is an optimization opportunity.
For instance, the most efficient parameter evaluation order can be
dependent on the calling convention, which is platform-dependent. For
instance on x86 and amd64 platforms the most efficient evaluation
order can very well be to evaluate right-to-left, since typical
calling conventions specify the last argument is to be pushed onto
the stack first[1]. (There are good reasons for that, mostly to do
with varargs)
In that case, it is possible for the compiler to detect if the
evaluation order matters, and if it doesn't (currently the only
allowed situation in D), it can push the arguments in any order it
pleases him.
<nitpick> Actually, if you check the spec it says the compiler is
allowed to issue an error if it detects the _result_ of the expression
depends on evaluation order. It doesn't seem to mention side-effects at
all, so evaluation order is technically allowed to matter (though it's
still an error to _depend_ on it). Well, unless you count side-effects
as part of the "result" of an expression... </nitpick>
To "depend on the evaluation order" is to have the evaluation order
matter. :)
--
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
↑ ↓ ← → Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Bruno Medeiros wrote:
Frits van Bommel wrote:
Bruno Medeiros wrote:
In that case, it is possible for the compiler to detect if the
evaluation order matters, and if it doesn't (currently the only
allowed situation in D), it can push the arguments in any order it
pleases him.
<nitpick> Actually, if you check the spec it says the compiler is
allowed to issue an error if it detects the _result_ of the expression
depends on evaluation order. It doesn't seem to mention side-effects
at all, so evaluation order is technically allowed to matter (though
it's still an error to _depend_ on it). Well, unless you count
side-effects as part of the "result" of an expression... </nitpick>
To "depend on the evaluation order" is to have the evaluation order
matter. :)
Yes, if you depend on it then it indeed matters.
But the other way around is not necessarily true; I think you can have a
program where evaluation order matters (e.g. different orders produce
different output) without the correctness actually _depending_ on it.
Both orders may be equally correct :).
↑ ↓ ← → James Dennett <jdennett acm.org> writes:
Bruno Medeiros wrote:
Frits van Bommel wrote:
Bruno Medeiros wrote:
Frits van Bommel wrote:
Bruno Medeiros wrote:
As we know, in C/C++ there are a lot of cases where the order of
evaluation of an expression is undefined.
i = i++;
c = a + (a = b);
func(++i, ++i);
D goes one step further by defining that any such behavior is illegal:
"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." in
http://www.digitalmars.com/d/expression.html .
Actually, if I read that right it just says that the order of
evaluation is undefined and should not be relied upon. Just like C/C++.
Read the paragraph ahead in the doc. In D that is considered a
language(i.e. compile) error and so the compiler can issue an error.
In C/C++ it is merely undefined program behavior, the code remains
compilable.
IIRC[1] the C++ standard includes "causes a compile error" as one of
the possible consequences of undefined behavior. I'm not sure about C.
[1] I've been staying away from C++ since I started using D, so this
is by no means a given...
I haven't read about C++ in detail, only C. But in both cases (and
sometimes here in the NG too) I often see the documents call "undefined
behavior" to thing they should call errors. They refer to these concepts
almost interchangeably, whereas they are not. They overlap a lot but
they are not the same, there is a subtle difference.
The difference is huge, not subtle. Using undefined
behavior (unless you're writing non-portable code and
your implementation offers an extension that defines
it) is *always* an error of a serious kind. Many
errors require diagnostics from a C or C++ compiler;
UB does not place *any* requirement on a compiler,
which is allowed to fail to translate the code, to
issue error messages, or to generate code that does
*anything*.
Dereferencing a trash pointer, for example, *is* an error. It *causes*
undefined behavior, but it *is not* merely undefined behavior: it *can
crash* your program.
Undefined behavior, formally, always has that potential.
(In fact, it might be reasonable to say that the only
ways to "crash" a C or C++ program are through the use
of undefined behavior, and it is certainly correct to
say that a crash is always a permitted consequence of
using undefined behavior.)
On the other hand if do
func(i++, i++);
where func simply prints prints its arguments, I will have undefined
program behavior, but no program error : that code *can not ever* crash
the program. (altough it is still likely a *conceptual* error)
It can crash your program, or cause it to fail to compile.
It's undefined behavior. Undefined behavior, unless
specifically allowed by your implementation, means that
all bets are off. Optimizers can assume that you won't
violate the sequence point rules, and can do unbounded
things with that information (for example).
This is a minor nitpick, since in practice both should be equally
avoided, but that subtle difference is still there.
Misunderstandings of what undefined behavior means are
common, but I'm not sure that your message clarifies.
(In C++ the order of evaluation is unspecified, not
undefined; this can mean that some code fragments have
UB because they violate rules on sequence points. This
uses the terms as per the ISO C++ standard.)
-- James
↑ ↓ ← → Manfred Nowak <svv1999 hotmail.com> writes:
Bruno Medeiros wrote
define an evaluation order for such expressions
- if a coder wants to define an order, she/he is free to use an
appropriate sequence of assignments
- if there is a predefined order, then
-- that predefined order must be learned by everyone
-- for every deviation of that order the appropriate sequence of
assignments must be coded anyway
-manfred
↑ ↓ ← → =?ISO-8859-1?Q?Lu=EDs_Marques?= <luismarques+spam gmail.com> writes:
Manfred Nowak wrote:
- if a coder wants to define an order, she/he is free to use an
appropriate sequence of assignments
- if there is a predefined order, then
-- that predefined order must be learned by everyone
-- for every deviation of that order the appropriate sequence of
assignments must be coded anyway
If there weren't performance issues I don't think there would be any
reason for the order not to be fixed. If someone knew the order they
could rely on it. If they didn't they could also order the assignments.
I don't think average programmers using Java even notice they learned
the evaluation order, they just do it intuitively.
For Java, the safety is more important. For D performance is.
--
Luís
↑ ↓ ← → =?ISO-8859-1?Q?Lu=EDs_Marques?= <luismarques+spam gmail.com> writes:
Manfred Nowak wrote:
- if a coder wants to define an order, she/he is free to use an
appropriate sequence of assignments
- if there is a predefined order, then
-- that predefined order must be learned by everyone
-- for every deviation of that order the appropriate sequence of
assignments must be coded anyway
If there weren't performance issues I don't think there would be any
reason for the order not to be fixed. If someone knew the order they
could rely on it. If they didn't they could also order the assignments.
I don't think average programmers using Java even notice they learned
the evaluation order, they just do it intuitively.
For Java, the safety is more important. For D performance is.
--
Luís
↑ ↓ ← → Walter Bright <newshound1 digitalmars.com> writes:
Bruno Medeiros wrote:
That's nice, but why not go all the way, and actually define an
evaluation order for such expressions.
I want to do that eventually, but it isn't easy to do. (There are also
issues with making it work with a C back end, where the C optimizer
reorders things according to what is legal C.)
↑ ↓ ← → Russell Lewis <webmaster villagersonline.com> writes:
Walter Bright wrote:
Bruno Medeiros wrote:
That's nice, but why not go all the way, and actually define an
evaluation order for such expressions.
I want to do that eventually, but it isn't easy to do. (There are also
issues with making it work with a C back end, where the C optimizer
reorders things according to what is legal C.)
To me, this sounds like a slam-dunk argument for never defining an
evaluation order. Why prevent optimizers from doing all that they can
conceive of? IMHO, the only places where you want to define evaluation
order is when it makes the program clearer, and the examples given are
(again, my opinion) examples of bad coding style. If you want to do
something complex, then code the steps in different statements; then
it's totally clear what you're trying to do - to both the compiler *and*
the guy maintaining your code 10 years from now.
Russ
↑ ↓ ← → Manfred Nowak <svv1999 hotmail.com> writes:
Russell Lewis wrote
Why prevent optimizers from doing all that they can conceive of?
This is not an issue, because the requirement is to define an order for
those cases only, where currently evaluation order matters. In all
other cases the compiler is free to choose the optimum the same way it
currently does.
-manfred
↑ ↓ ← → Russell Lewis <webmaster villagersonline.com> writes:
Manfred Nowak wrote:
Russell Lewis wrote
Why prevent optimizers from doing all that they can conceive of?
This is not an issue, because the requirement is to define an order for
those cases only, where currently evaluation order matters. In all
other cases the compiler is free to choose the optimum the same way it
currently does.
I don't understand what you're saying here; perhaps your definition was
too indirect? What are you wanting to define orders for, and what not?
Moreover, if it's not an issue, then why did Walter bring it up?
Apparently it *is* an issue.
↑ ↓ ← → Sean Kelly <sean f4.ca> writes:
Russell Lewis wrote:
Manfred Nowak wrote:
Russell Lewis wrote
Why prevent optimizers from doing all that they can conceive of?
This is not an issue, because the requirement is to define an order
for those cases only, where currently evaluation order matters. In all
other cases the compiler is free to choose the optimum the same way it
currently does.
I don't understand what you're saying here; perhaps your definition was
too indirect? What are you wanting to define orders for, and what not?
Moreover, if it's not an issue, then why did Walter bring it up?
Apparently it *is* an issue.
It's an issue because it's confusing, as previous discussions can
attest. I'm still not convinced that there is sufficient reason to
define an evaluation order, since most other languages don't and it
doesn't seem to be a problem, but I'll admit that it would make for less
confusion.
Sean
↑ ↓ ← → Russell Lewis <webmaster villagersonline.com> writes:
Sean Kelly wrote:
It's an issue because it's confusing, as previous discussions can
attest. I'm still not convinced that there is sufficient reason to
define an evaluation order, since most other languages don't and it
doesn't seem to be a problem, but I'll admit that it would make for less
confusion.
Maybe a simpler solution (harder for Walter, probably, but simpler for
everybody else) would be to have the compiler start issuing errors when
these undefined syntaxes are used. :)
↑ ↓ ← → Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Sean Kelly wrote:
Russell Lewis wrote:
Manfred Nowak wrote:
Russell Lewis wrote
Why prevent optimizers from doing all that they can conceive of?
This is not an issue, because the requirement is to define an order
for those cases only, where currently evaluation order matters. In
all other cases the compiler is free to choose the optimum the same
way it currently does.
I don't understand what you're saying here; perhaps your definition
was too indirect? What are you wanting to define orders for, and what
not?
Moreover, if it's not an issue, then why did Walter bring it up?
Apparently it *is* an issue.
It's an issue because it's confusing, as previous discussions can
attest. I'm still not convinced that there is sufficient reason to
define an evaluation order, since most other languages don't and it
doesn't seem to be a problem, but I'll admit that it would make for less
confusion.
Sean
What do you mean by "most other languages"? Have you seen my other post
which mentions that not only Java, but C#, Python, and even Ruby all
have well defined evaluation orders?
--
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
↑ ↓ ← → Sean Kelly <sean f4.ca> writes:
Bruno Medeiros wrote:
Sean Kelly wrote:
It's an issue because it's confusing, as previous discussions can
attest. I'm still not convinced that there is sufficient reason to
define an evaluation order, since most other languages don't and it
doesn't seem to be a problem, but I'll admit that it would make for
less confusion.
What do you mean by "most other languages"? Have you seen my other post
which mentions that not only Java, but C#, Python, and even Ruby all
have well defined evaluation orders?
True. I suppose I should have said "most other languages I've used" :-p
I'm wondering if it's fair to include languages that don't support
operator overloading though, or multiple calling conventions. Can a
strong parallel be drawn between D and any of the languages you mention,
insofar as this issue is concerned?
Sean
↑ ↓ ← → Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Sean Kelly wrote:
Bruno Medeiros wrote:
Sean Kelly wrote:
It's an issue because it's confusing, as previous discussions can
attest. I'm still not convinced that there is sufficient reason to
define an evaluation order, since most other languages don't and it
doesn't seem to be a problem, but I'll admit that it would make for
less confusion.
What do you mean by "most other languages"? Have you seen my other
post which mentions that not only Java, but C#, Python, and even Ruby
all have well defined evaluation orders?
True. I suppose I should have said "most other languages I've used" :-p
I'm wondering if it's fair to include languages that don't support
operator overloading though, or multiple calling conventions. Can a
strong parallel be drawn between D and any of the languages you mention,
insofar as this issue is concerned?
Sean
C# does support operator overload. Dunno about Python and Ruby.
But I don't see how operator overloading or calling conventions would
have any effect on having a completely defined expression order of
evaluation. Indeed, I don't think it makes any difference.
--
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
↑ ↓ ← → Daniel Keep <daniel.keep.lists gmail.com> writes:
Bruno Medeiros wrote:
C# does support operator overload. Dunno about Python and Ruby.
But I don't see how operator overloading or calling conventions would
have any effect on having a completely defined expression order of
evaluation. Indeed, I don't think it makes any difference.
Python:
class FakeInt:
self.v = v
def __add__(self, rhs):
return FakeInt(self.v+rhs.v)
def __str__(self):
return str(self.v)
FakeInt(2) + FakeInt(3)
-- Daniel
--
int getRandomNumber()
{
return 4; // chosen by fair dice roll.
// guaranteed to be random.
}
http://xkcd.com/
v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D
i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
↑ ↓ ← → Sean Kelly <sean f4.ca> writes:
Jan Claeys wrote:
Op Fri, 27 Apr 2007 18:42:12 -0700
schreef Sean Kelly <sean f4.ca>:
Bruno Medeiros wrote:
Sean Kelly wrote:
It's an issue because it's confusing, as previous discussions can
attest. I'm still not convinced that there is sufficient reason
to define an evaluation order, since most other languages don't
and it doesn't seem to be a problem, but I'll admit that it would
make for less confusion.
post which mentions that not only Java, but C#, Python, and even
Ruby all have well defined evaluation orders?
used" :-p I'm wondering if it's fair to include languages that don't
support operator overloading though, or multiple calling
conventions.
Python supports operator overloading and "multiple calling
conventions"? ;-)
Ah well :-) I suppose I'm just worried we'd be trading away a potential
for optimization for support of a coding strategy that no one should be
using anyway.
Sean
↑ ↓ ← → Manfred Nowak <svv1999 hotmail.com> writes:
Russell Lewis wrote
Manfred Nowak wrote:
Russell Lewis wrote
Why prevent optimizers from doing all that they can conceive of?
This is not an issue, because the requirement is to define an
order for those cases only, where currently evaluation order
matters. In all other cases the compiler is free to choose the
optimum the same way it currently does.
I don't understand what you're saying here; perhaps your
definition was too indirect? What are you wanting to define
orders for, and what not?
Have a look at one of Brunos examples:
| c = a + (b = c);
There seem to exist some cases where evaluation order matters.
This is because the coder might have believed in evaluating this
expression as the sequence:
b = c;
c = a + b; // c == a + c
or as the sequence:
c = a + b;
b = c; // b == a + c
which might be different, if one of the following conditions holds:
a != 0
b != c
If it can be deduced from the context, that none of this conditions
holds, then there is no need to define an order and thus no need to
"prevent optimizers from doing all that they can conceive of".
OTOH if it can be deduced from the context, that at least one of this
conditions might hold then Brunos requirement kicks in.
Moreover, if it's not an issue, then why did Walter bring it up?
Apparently it *is* an issue.
-manfred
↑ ↓ ← → Manfred Nowak <svv1999 hotmail.com> writes:
Walter Bright wrote
it isn't easy to do
If it is not easy to define the order for the specs,
then it will not be easy to learn,
then near to nobody will know of or rely on the definition in the
specs.
Remember that even M$ recommends to fully parenthese expressions
<because others might not know how to evaluate expressions without
parentheses>.
You once said, that you want to prohibit the upcoming of D-guru's. But
if you yourself are not able to immediately sketch such order here,
then you have the proof of upcoming gurus.
If it is not easy to code then above arguments holds for compiler
writers too.
-manfred
↑ ↓ ← → Walter Bright <newshound1 digitalmars.com> writes:
Manfred Nowak wrote:
Walter Bright wrote
it isn't easy to do
If it is not easy to define the order for the specs,
It's easy to define the order. It is not so easy to implement it.
↑ ↓ ← → Manfred Nowak <svv1999 hotmail.com> writes:
Walter Bright wrote
It's easy to define the order.
Then please do so right now.
-manfred
↑ ↓ ← → Walter Bright <newshound1 digitalmars.com> writes:
Manfred Nowak wrote:
Walter Bright wrote
It's easy to define the order.
Then please do so right now.
Then I'd have a pile of bug reports because it isn't so easy to implement.
↑ ↓ ← → Manfred Nowak <svv1999 hotmail.com> writes:
Walter Bright wrote
Then I'd have a pile of bug reports because it isn't so easy to
implement.
Why that, when it isn't in the specs, only in this forum, and declared
as a draft definition?
Please do not declare that the thinking capabilities of average D-users
are that low.
-manfred
↑ ↓ ← → Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Manfred Nowak wrote:
Walter Bright wrote
Then I'd have a pile of bug reports because it isn't so easy to
implement.
Why that, when it isn't in the specs, only in this forum, and declared
as a draft definition?
Please do not declare that the thinking capabilities of average D-users
are that low.
-manfred
I don't think he means bugs in users' code (although there would probably be a
handful of
them, most likely quick-fixes though). I think he actually means bugs in the
compiler,
which are worth more time spent investigating implementation details to avoid.
-- Chris Nicholson-Sauls
↑ ↓ ← → Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Manfred Nowak wrote:
Walter Bright wrote
Then I'd have a pile of bug reports because it isn't so easy to
implement.
Why that, when it isn't in the specs, only in this forum, and declared
as a draft definition?
Please do not declare that the thinking capabilities of average D-users
are that low.
-manfred
Someone with a non-low average thinking capability (*grin* :) ) would
easily deduce that the evaluation order will be the same as any other
modern programming language (not just Java, but C#, Python, even Ruby,
have all the same evaluation order). The rule in a general sense is:
Evaluate operands in the same order as the associativity rule of the
operator.
So stuff like this:
c = a + (b = c);
evaluates in this order:
a
c
b
(b = c)
a + (b = c)
c
c = a + (b = c)
A function call, since it is basicly an operator that takes a function
value and arguments as operands, works in the same rule. So:
func(++i, ++c);
evaluates:
func
++i
++c
func(++i, ++c)
I don't think there is any significant learning process involved here.
If you know the associativity rules (which you should), then the
evaluation order is simply what naturally follows from there. You don't
have to memorize a whole different set of rules. In fact the assignments
are basicly the only operators where the operands are evaluated
right-to-left.
--
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
↑ ↓ ← → Russell Lewis <webmaster villagersonline.com> writes:
Bruno Medeiros wrote:
Someone with a non-low average thinking capability (*grin* :) ) would
easily deduce that the evaluation order will be the same as any other
modern programming language (not just Java, but C#, Python, even Ruby,
have all the same evaluation order). The rule in a general sense is:
Be careful when you imply "everybody who thinks differently than I is
stupid." I can confidently state that I have non-low average thinking
capability, and it is far from clear to me. I had to look pretty hard
at your analysis below to make sure that I knew what seemed so "obvious"
to you.
My simple question is: why are we worrying about defining the behavior
of code snippets which are bad coding style? There are clearer, more
explicit ways to accomplish the same task, that do not require that we
define the order of operations.
Evaluate operands in the same order as the associativity rule of the
operator.
So stuff like this:
c = a + (b = c);
evaluates in this order:
a
c
b
(b = c)
a + (b = c)
c
c = a + (b = c)
A function call, since it is basicly an operator that takes a function
value and arguments as operands, works in the same rule. So:
func(++i, ++c);
evaluates:
func
++i
++c
func(++i, ++c)
I don't think there is any significant learning process involved here.
If you know the associativity rules (which you should), then the
evaluation order is simply what naturally follows from there. You don't
have to memorize a whole different set of rules. In fact the assignments
are basicly the only operators where the operands are evaluated
right-to-left.
If there is no significant learning process involved, then why did you
need to state it here? Surely everybody knew the rules already. If not
everybody knew the rules, there is a learning process involved...and
apparently it's nontrivial, at least to some people.
↑ ↓ ← → Manfred Nowak <svv1999 hotmail.com> writes:
Bruno Medeiros wrote
Evaluate operands in the same order as the associativity rule
of the
operator.
You require all operators to have an associativity? Then what is the
associativity of the operators for comparison?
So stuff like this:
c = a + (b = c);
evaluates in this order:
A function call, since it is basicly an operator that takes a
function value and arguments as operands, works in the same rule.
Then imagine an arbitrary sequence of assignments: are you able to
identify the regions of that sequence that are in existence only
because the coder wants to use an ordering other then the predefined?
If you are able to do so
and someone declares that he is not able to do so
then how would you teach him that capability of yours?
Please start immediately under the fiction, that I am not able to
identify those regions.
-manfred
↑ ↓ ← → Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Manfred Nowak wrote:
Bruno Medeiros wrote
Evaluate operands in the same order as the associativity rule
of the
operator.
You require all operators to have an associativity? Then what is the
associativity of the operators for comparison?
Huh? "require all operators to have an associativity"?... Any C-based
language has an associativity rule for all operators! Didn't you know
that?? The associativity for comparison operators is listed here:
http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B
(it's the same in D)
--
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
↑ ↓ ← → Manfred Nowak <svv1999 hotmail.com> writes:
Bruno Medeiros wrote
(it's the same in D)
changelog for D 1.007
Sadly you seem unwilling to state your capabilities with respect to
identifying assignment subsequences wich can be specifically
attributed.
-manfred
↑ ↓ ← → Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Manfred Nowak wrote:
Bruno Medeiros wrote
(it's the same in D)
changelog for D 1.007
Hum, you're right, I forgot about that, sorry.
So, going back to your original question:
Manfred Nowak wrote:
Bruno Medeiros wrote
Evaluate operands in the same order as the associativity rule
of the
operator.
You require all operators to have an associativity? Then what is the
associativity of the operators for comparison?
Ok, I understand the question. Very well, let's use a different learning
rule:
All operands are evaluated left to right, with the exception of the
assignment operators which are evaluated right-to-left.
I think it is even easier to learn than the previous one. Any problem
with this one?
--
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
↑ ↓ ← → Manfred Nowak <svv1999 hotmail.com> writes:
Bruno Medeiros wrote
All operands are evaluated left to right, with the exception of
the assignment operators which are evaluated right-to-left.
Any problem with this one?
Don't you see a reason why Walter has tossed himself out of this
thread?
Given an expression `a op b'
| The expression is rewritten as both:
| a.opfunc(b)
| b.opfunc_r(a)
This is from the specs! Now what is the evaluation order of `a op b'?
`a' then `b'?
`b' then `a'?
If there is a cloud some people only see the silver lining.
-manfred
↑ ↓ ← → Benji Smith <dlanguage benjismith.net> writes:
Manfred Nowak wrote:
If there is a cloud some people only see the silver lining.
That's a great phrase! I'm stealing it for my own purposes :-) Thanks!
--benji
↑ ↓ ← → Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Manfred Nowak wrote:
Bruno Medeiros wrote
All operands are evaluated left to right, with the exception of
the assignment operators which are evaluated right-to-left.
Any problem with this one?
Don't you see a reason why Walter has tossed himself out of this
thread?
Given an expression `a op b'
| The expression is rewritten as both:
| a.opfunc(b)
| b.opfunc_r(a)
This is from the specs! Now what is the evaluation order of `a op b'?
`a' then `b'?
`b' then `a'?
If there is a cloud some people only see the silver lining.
-manfred
Hum, good point. This looks like an unprecedented case, I don't know if
any other languages have reverse operator overloading like D. In any
case a design decision would have to be made (thus creating a new
evaluation rule).
I would say that the order should be 'a' then 'b', because this way the
programmer doesn't have to check which operator function is being
invoked to know the evaluation order of such expression. This makes the
code less dependent, which is particularly important since the
underlying operator function could change in time, (from a non-reverse,
to a reverse one, for example), and it would be best to maintain the
original order semantics.
--
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
↑ ↓ ← → Daniel Keep <daniel.keep.lists gmail.com> writes:
Bruno Medeiros wrote:
Hum, good point. This looks like an unprecedented case, I don't know if
any other languages have reverse operator overloading like D.
Rubbish. Python does as well, and for precisely the same reason I
suspect D does: non-commutative operations, and working with existing,
closed types. For instance, if you have a pre-existing, closed vector
class, and you want to write a matrix class that works with it, you need
to overload both opMul and opMul_r, or it won't work. I'd argue that
any language that *doesn't* let you write the reverse operation is doing
a pretty half-arsed job of operator overloading...
Hell, I wrote vector and matrix structs from scratch, and I did it that
way since having two templates depend on each other causes MORE than
enough problems... I'm not entirely sure I fixed the data corruption
issue it was causing, and I'd really rather not wrangle with that again.
-- Daniel
--
int getRandomNumber()
{
return 4; // chosen by fair dice roll.
// guaranteed to be random.
}
http://xkcd.com/
v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D
i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
↑ ↓ ← → Manfred Nowak <svv1999 hotmail.com> writes:
Bruno Medeiros wrote
In any case a design decision would have to be made
There is at least one more such decision to be made.
But what are they worth when it is anticipated, that the hardware will
be able to evaluate complex expressions if there are no evaluation
orders to be followed.
-manfred
↑ ↓ ← → janderson <askme me.com> writes:
Manfred Nowak wrote:
Walter Bright wrote
it isn't easy to do
If it is not easy to define the order for the specs,
then it will not be easy to learn,
then near to nobody will know of or rely on the definition in the
specs.
Remember that even M$ recommends to fully parenthese expressions
<because others might not know how to evaluate expressions without
parentheses>.
You once said, that you want to prohibit the upcoming of D-guru's. But
if you yourself are not able to immediately sketch such order here,
then you have the proof of upcoming gurus.
If it is not easy to code then above arguments holds for compiler
writers too.
-manfred
I agree. Furthermore, I strongly think it should be left as is. Why,
because when I comeup against weird code like that, I don't want to have
to consult the spec. Its like implicit casting, if you don't know what
is happening your going to have a terrible time figuring out what is
happening.
This is one area where I think D could do a lot more to help the
programmer avoid mistakes.
Furthermore if its difficult to implement, you've just made D harder for
someone else to implement.
Please reconsider putting this in.
-Joel
↑ ↓ ← → Jan Claeys <usenet janc.be> writes:
Op Fri, 27 Apr 2007 18:42:12 -0700
schreef Sean Kelly <sean f4.ca>:
Bruno Medeiros wrote:
Sean Kelly wrote:
It's an issue because it's confusing, as previous discussions can
attest. I'm still not convinced that there is sufficient reason
to define an evaluation order, since most other languages don't
and it doesn't seem to be a problem, but I'll admit that it would
make for less confusion.
What do you mean by "most other languages"? Have you seen my other
post which mentions that not only Java, but C#, Python, and even
Ruby all have well defined evaluation orders?
True. I suppose I should have said "most other languages I've
used" :-p I'm wondering if it's fair to include languages that don't
support operator overloading though, or multiple calling
conventions.
Python supports operator overloading and "multiple calling
conventions"? ;-)
--
JanC
|
|