42 ms·
Interesting, my intuition is the opposite: that left-to-right evaluation is clearly the better approach. I just tested a few languages and it turns out that the
by alangpierce 8y ago
Interesting, my intuition is the opposite: that left-to-right evaluation is clearly the better approach. I just tested a few languages and it turns out that there's no clear agreed-upon answer, but LHS first seems to be more common at least for recent languages:
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.
- bArray 8y agoAnd this is why I tend to use a slightly smaller subset of some of the features that C-family languages support, along with an abundance of brackets. 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"...
- lern_too_spel 8y agoDon't do that. The behavior is explicitly undefined in C. http://c-faq.com/expr/seqpoints.html http://c-faq.com/expr/seqpoints.html
- oblio 8y agoDon't do what, precisely? He listed several examples. And I think he's agreeing with you, he's just sarcastic.
- lern_too_spel 8y agoHe said, "this is why I tend to use a slightly smaller subset of some of the features that C-family languages support, along with an abundance of brackets." C does not support his first example. The standard states that the behavior is undefined.
- bArray 8y ago> If I remember rightly [..] 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.
- quickthrower2 8y agoI've recently started working on a code base with great comments and they are worth their weight in gold. Especially class and method level description comments. And doubly especially the class level ones. Also there is none of the code golf in there that you have just given as an example.
- zbentley 8y ago> z = a > b ? c < d ? e : f : g ? h : i 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.
- pjmlp 8y agoIt gets better when you compile that C code as C++, as ?: has a different precedence level.
- masonic 8y agoIs there no language in which evaluation order is random/undefined?
- kryptiskt 8y agoScheme doesn't define an evaluation order.
- alangpierce 8y agoAs mentioned elsewhere, it's unspecified in C but tends to be right-to-left in practice. To be clear, my categorization of languages is just from testing it directly, I didn't look it up in the spec for any of them. But I think newer languages try to have fully-defined behavior, at least for things like this.
- duckerude 8y agoRHS seems right to me because it means the actions on the LHS happen consecutively. 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.
- alangpierce 8y agoI think it depends on how you think about it. As mentioned elsewhere, "=" is a special statement syntax rather than an operator in Python, but if you were to think of it like an operator, it would be evaluated in three phases: (1) evaluate one side, (2) evaluate the other side, (3) perform operation. The __setitem__ method defines how the left side participates in step 3, but IMO there's a separate LHS evaluation step that's independent of the assignment itself. 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.
- carlbordum 8y agoIn Python `=` is not just a binary operator. Python is evaluated left-to-right (but not on assignment).