Is there some advantage to LHS-first that I can't think of?
Is there some advantage to LHS-first that I can't think of?
LHS first: JavaScript, Java, Go, C#, Swift, PHP, Ruby
RHS first: C++, Python, Rust
I ran this sort of code for all of them:
def lhs(): print "LHS"; return 0
def rhs(): print "RHS"; return 0
a = [0]
a[lhs()] = rhs()
"=" is syntactically just a binary operator, so I expect it to behave like other binary operators (and AFAIK all other binary operators evaluate left-to-right in almost all languages). It's special because the LHS evaluates to an assignable reference rather than to a value, but nothing stops you from evaluating the left side in full before starting to evaluate the right side. As with every binary operator, it's possible to write code such that the evaluation of one side affects the result of evaluating the other side, but of course that sort of code is really fragile anyway.If I remember rightly, there is the example:
a = {-1, -1}
x = 0
a[++x] = x
print(a[0] + " " + a[1])
Depending on the language (and sometimes even if you have optimizations set for those that compile to binaries), you'll get a different answer.I always love (read sarcasm) to see awesome code, such as:
z = a & b > c | d
or: z = a > b ? c < d ? e : f : g ? h : i
And then of course, the statement: "my code doesn't need comments because the code comments itself"...And I think he's agreeing with you, he's just sarcastic.
C does not support his first example. The standard states that the behavior is undefined.
You're probably not wrong, but I specifically remember there was something you could do in order to trick the compiler to allow modification on the left hand side to happen. It could possibly be by having two variable names referencing the same variable - for example.
Besides, the whole point was that it's usually not clever "trying to be clever". It just creates confusion. I don't personally believe the majority of people need to test the entire C spec to it's absolute boundary. A subset serves most people perfectly well.
Also there is none of the code golf in there that you have just given as an example.
That's stylistically ugly but not hard to predict; at some point I had it beaten into my head that ternaries are always at the bottom of the single-character operator precedence stack (I really hope all languages stick to that). I'd expect most people to know this.
> z = a & b > c | d
That is harder to predict. I wouldn't expect most people to know this one without looking up a precedence list.
To expand your example a bit:
class ShoutyContainer:
def __setitem__(self, index, value):
print("Assignment")
def lhs(): print("LHS")
def rhs(): print("RHS")
a = ShoutyContainer()
a[lhs()] = rhs()
Yields: RHS
LHS
Assignment
If LHS were evaluated first, then it would be separated from the final assignment step by the RHS evaluation. That would be odd.You might call this code snippet analogous:
class ShoutyNumber:
def __init__(self, n):
self.n = n
print(f'Created {self.n}')
def __add__(self, other):
print(f'Added with {self.n}')
return self.n + other.n
ShoutyNumber(1) + ShoutyNumber(2)
Yields: Created 1
Created 2
Added with 1
But I understand that in some mental models and some implementations, it's cleaner to have the entire RHS value ready before starting any evaluation of the LHS. I think that avoids the need to have "assignable reference" as a special type of expression result.I did not check C++ but for C, according to ISO/IEC 9899:1999 section 6.5.16 paragraph 4 on the semantics of the assignment operator: "The order of evaluation of the operands is unspecified."
t-order.c:10:8: warning: unsequenced modification and access to 'x' [-Wunsequenced]
foo[x++] = x;Think of lisp But then lisp require parentheses
Think of j but the strange right hand side then fork/train.
It is hard for this simple thing. Even = and =: get Python dictator for life resigned.
Just hard
The problem here, in any case, isn't the order of evaluation. It's that the array bound check is done at the wrong time.
0 - https://golang.org/ref/spec#Assignments 1 - https://golang.org/ref/spec#Order_of_evaluation
In places like Australia and America, if you have a group of people and you’re going round them (e.g. reading in turns or playing various card games), you’d be more likely to go clockwise from on top rather than counter-clockwise.
But in India, they naturally go counter-clockwise from on top rather than clockwise, and I once saw someone playing a game of hearts on a phone there, and it was going counter-clockwise.
Localisation definitely entails more than just translating strings. Layout and functionality changes can be involved.
Dealing is done either clockwise or counterclockwise. If this is omitted from the rules, then it should be assumed to be:
* clockwise for games from North America, North and West Europe and Russia; * counterclockwise for South and East Europe and Asia, also for Swiss games and all Tarot games.
For better or worse left-to-right has "won" in programming-land and I fully agree with alangpierce that it's the natural choice for evaluation order as well. We read left-to-right and the computer should as well. That's one of the main problems I have with Python. Evaluating right-to-left just feels like being contrarian.
That’s a reason it matters which one is evaluated first, but not a reason to evaluate the RHS first.
It's been a while, however, so I might be remembering wrong (or indeed have misunderstood).