-
Notifications
You must be signed in to change notification settings - Fork 373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Arguments aren't always evaluated left to right #1342
Comments
This is unquestionably counterintuitive, but what else would you have
compiles to
; notice that
and for
? It's not obvious to me that this strategy will work in general. Think hard about what you want. |
This also happens to => [(setv foo 1) foo (setv foo 2) foo]
foo = 1
foo = 2
[None, foo, None, foo]
[None, 2, None, 2] The expected answer was |
Python guarantees the sequential order of evaluation in displays and function calls. Programs may rely on this for correct behavior. If Hy is allowed to reorder things this must, at least, be documented. But how do we even document this? I notice these things quickly because I almost always have the Now that we don't have
I don't have to know the answer to that to report it as a problem. But perhaps we should pull everything out of a display expression or function call if we pull one thing out. Examples: [(setv foo 1) foo (setv foo 2) foo] foo = 1
_hy_anon_var_1 = None
_hy_anon_var_2 = foo
foo = 2
_hy_anon_var_3 = None
_hy_anon_var_4 = foo
[_hy_anon_var_1, _hy_anon_var_2, _hy_anon_var_3, _hy_anon_var_4] [foo (del foo)] _hy_anon_var_1 = foo
del foo
_hy_anon_var_2 = None
[_hy_anon_var_1, _hy_anon_var_2] (f (g) (with [(E)] (h))) _hy_anon_var_1 = g()
with E():
_hy_anon_var_2 = h()
f(_hy_anon_var_1, _hy_anon_var_2) |
Certainly, but it's a question we have to answer if we want to ever fix a bug. |
I think it would always work in the case of display expressions and function calls, since things should be evaluated once each in sequence. We can fix that at least. When things should be evaluated some other number of times (like zero in the Are there other loop or branch cases that have this problem? Or do you have a counterexample for displays or function calls? |
Thinking about this some more, I think it would suffice if we pulled out everything before the statement, instead of just everything. Any expressions afterwards should work fine directly in the display or call, so
could compile to
It would save assignments, but I'm not sure if it would be harder to implement. |
We'd definitely want to put nested cases in the tests, to make sure things still happen in strict left-to-right order. But it could totally work. [0 (setv x 1) x [1 (setv x 2) x 3 4] x] _hy_anon_var_1 = 0
x = 1
_hy_anon_var_2 = None
_hy_anon_var_3 = x
_hy_anon_var_5 = 1
x = 2
_hy_anon_var_6 = None
_hy_anon_var_4 = [_hy_anon_var_5 _hy_anon_var_6 x 3 4]
[_hy_anon_var_1 _hy_anon_var_2 _hy_anon_var_3 _hy_anon_var_4 x]
|
@kirbyfan64 this seems similar to what we did for |
... probably. It would have to be a bit different, but I'm pretty sure it would work. |
Thinking about this some more, the compiler should be able to detect if an element is a simple constant literal (like a quoted symbol or an int). With the possible exception of f-strings (which aren't really constant), literals are not going to change due to side effects. So my last example x = 1
_hy_anon_var_1 = None
_hy_anon_var_2 = x
x = 2
_hy_anon_var_4 = None
_hy_anon_var_3 = [1 _hy_anon_var_4 x 3 4]
[0 _hy_anon_var_1 _hy_anon_var_2 _hy_anon_var_3 x] Furthermore, certain special forms are known to the compiler to always return
But these are just optimizations. Pulling out everything when there's a statement will work correctly. |
For example,
The expected result was
[42, None]
.The text was updated successfully, but these errors were encountered: