assignment: left-to-right or right-to-left evaluation?

Nick Sabalausky a at a.a
Sat May 9 13:14:02 PDT 2009


"Andrei Alexandrescu" <SeeWebsiteForEmail at erdani.org> wrote in message 
news:gu4bqu$bq$1 at digitalmars.com...
> Consider:
>
> uint fun();
> int gun();
> ...
> int[] a = new int[5];
> a[fun] = gun;
>
> Which should be evaluated first, fun() or gun()? It's a rather arbitrary 
> decision. C/C++ don't even define an order. Python chooses left-to-right, 
> EXCEPT for assignment, which is right-hand side first. Lisp and C# choose 
> consistent left-to-right. I don't like exceptions and I'd like everything 
> to be left-to-right. However, this leads to some odd cases. Consider this 
> example in TDPL:
>

This may sound strange coming from me, but I think I actually like the 
Python way of doing it. I may be getting slightly ahead of myself by saying 
this, but I think the inconsistency lies more with the assignment statement 
itself than function evaluation order.

First of all:

lvalue = expression;

Anyone with any real experience in imperative programing looks at that and 
sees "expression (on the right) gets evaluated, and then the result gets 
placed into lvalue (on the left)". If both sides contain a function call, 
and the functions in the lvalue get exaluated first, then that would seem to 
contradict the intuitive understanding of the assignment's natural 
right-to-left order.

I might be venturing slightly offtopic here, but lately, I've been giving a 
bit of thought to matters of left/right directions. Consider the following:

fooA(); fooB(); fooC();

Flow of execution can be followed left-to-right. Which makes sense, because 
most of the more common (human) languages are left-to-right. But then 
there's:

lvalue = fooC(fooB(fooA(stuff)))

Now all of a sudden, it's all completely reversed! If you want to follow 
this statement's flow-of-execution step-by-step, the entire thing goes 
right-to-left: First stuff is evaluated, then fooA is called, then fooB is 
called, then fooC is called, then a value gets assigned to lvalue. Of 
course, function chaining syntax has been gaining popularity, so in *some* 
cases you may be able to fix the ordering of the right-hand-side:

lvalue = stuff.fooA().fooB().fooC();

(Which, of course, also has the side-benefit of reducing parenthesis-hell). 
Now, at least the right-hand-side, reads completely in a natural 
left-to-right order.

However, there are languages out there that flip the assignment:

auto num;
5 => num;

I've never actually liked that in the past. I literally grew up using 
ApplesoftBASIC and QBASIC, which use the more common "target_var = 
expression" syntax, so the few times I came across the above, it always felt 
awkward and uncomfortable. But lately, because of all of this, I've been 
starting to think "expr => target_var" does have its merits. Of course, the 
downside is one could argue that "lvalue = fooC(fooB(fooA(stuff)))" reads in 
order from "general overview" to "more specific", and with 
"stuff.fooA().fooB().fooC() => target_var;" you have to go all the way to 
the end to see the general idea of what's finally gotten accomplished.

The reason I bring all this up is because that (not that it's likely to 
actually happen in D) would allow the sensible Python-style of "functions in 
the expression get evaluated before functions on the assignment-side" 
*without* making any exceptions to the left-to-right rule (which, as I 
pointed out before, is really more of an exception with the basic assignment 
syntax).





More information about the Digitalmars-d mailing list