Inline assignment expression
http://bugs.python.org/issue1714448 had an interesting proposal that I thought might be worthwhile discussing here. if something as x: however, of greater use would be assignment expressions that allow: if (something as x) == other: # can now use x. I propose that we implement assignment expressions that would allow assignments to be made any place that expressions are currently valid. The proposal uses the (nominal) right arrow (RARROW) '->' to indicate the assignment. The form would look like this: EXPR -> VAR which translates to VAR = EXPR (EXPR) Expression (EXPR) is evaluated and assigned to target VAR. The value of EXPR is left on the top of stack. another toy example to think about: while len(expensive() -> res) == 4: dosomething(res) A patch has been uploaded to the named issue in the bug tracker. I encourage you to try it out (py3k at the moment). As I mentioned earlier the exact syntax is only nominal. We needn't use the RARROW if consensus is against that, it is a simple operation to change this to any of ('becomes', 'into', 'assigns' ... I look forward to your comments. Cheers, Jervis
If we're going to allow unconstrained assignments inside expressions why don't we use the same syntax as C, C++, Java, JavaScript etc.? But I left this out intentionally for a reason. We would need to have a great deal of evidence that it was a mistake for making a U-turn. Have a happy discussion, --Guido <extricates himself> On Sat, Mar 14, 2009 at 6:47 AM, Jervis Whitley <jervisau@gmail.com> wrote:
http://bugs.python.org/issue1714448 had an interesting proposal that I thought might be worthwhile discussing here.
if something as x:
however, of greater use would be assignment expressions that allow: if (something as x) == other: # can now use x.
I propose that we implement assignment expressions that would allow assignments to be made any place that expressions are currently valid. The proposal uses the (nominal) right arrow (RARROW) '->' to indicate the assignment. The form would look like this:
EXPR -> VAR
which translates to
VAR = EXPR (EXPR)
Expression (EXPR) is evaluated and assigned to target VAR. The value of EXPR is left on the top of stack.
another toy example to think about:
while len(expensive() -> res) == 4: dosomething(res)
A patch has been uploaded to the named issue in the bug tracker. I encourage you to try it out (py3k at the moment). As I mentioned earlier the exact syntax is only nominal. We needn't use the RARROW if consensus is against that, it is a simple operation to change this to any of ('becomes', 'into', 'assigns' ...
I look forward to your comments.
Cheers,
Jervis _______________________________________________ Python-ideas mailing list Python-ideas@python.org http://mail.python.org/mailman/listinfo/python-ideas
-- --Guido van Rossum (home page: http://www.python.org/~guido/)
why don't we use the same syntax as C, C++, Java, JavaScript etc.?
I have deliberately chosen to use a different syntax (right assignment for one, and a different, albeit nominal, operator) than C, C++ to address the concern that a user may unintentionally assign when they wanted to compare. http://bugs.python.org/issue1714448 the issue that I was responding to, also recognised the need to move away from a C style assignment for a similar situation (I have also written a patch, not posted yet, to address their situation.)
But I left this out intentionally for a reason. We would need to have a great deal of evidence that it was a mistake for making a U-turn.
I realise that this is a trivial (to implement) patch and that it must have been left out of Python for a reason, however I am sure that using an explicit and elegant enough syntax that this can shake the feeling that it is un-pythonic. I have drafted a PEP with some of the basic discussion included and some example situations. It does however, fail to discuss issues of precedence and implementations in other languages at this stage. As implemented the precedence for this operation is just below a BoolOp and above a BinOp so things like test() as x == answer should work and (for example) 4 * 4 as x == 16 # True I read your answer as a -0.5, if it is dead in the water, let me know we can close the Issue as a 'Wont Fix'. Cheers, Jervis
Jervis Whitley wrote:
[Guido]
But I left this out intentionally for a reason. We would need to have a great deal of evidence that it was a mistake for making a U-turn.
I read your answer as a -0.5, if it is dead in the water, let me know we can close the Issue as a 'Wont Fix'.
Having read similar discussions over the last decade, I read it as about -.995 ;-) In other words, not quite as dead as adding braces, but close. tjr
Jervis Whitley wrote:
so things like
test() as x == answer
should work and (for example)
4 * 4 as x == 16 # True
Would "4 * 4 == 16 as x" be equivalent to "(4 * 4 == 16) as x" or "4 * 4 == (16 as x)"? Either way, I suspect this is dead in the water, but I guess that issue should be clarified. -- Carl
Would "4 * 4 == 16 as x" be equivalent to "(4 * 4 == 16) as x" or "4 * 4 == (16 as x)"?
Either way, I suspect this is dead in the water, but I guess that issue should be clarified.
This is one of the matters for discussion here. I much prefer the latter, that is the assignment expression has precedence below that of BoolOp but above BinOp. Cheers. Try running the patch, if nothing else kicking the tires a bit is a bit of fun (note that i nominally use '->' instead of 'as' in the patch.) I know that since writing it, it has been if nothing else, fun, doing assignments in expressions.
On Sat, Mar 14, 2009 at 3:52 PM, Jervis Whitley <jervisau@gmail.com> wrote:
I read your answer as a -0.5, if it is dead in the water, let me know we can close the Issue as a 'Wont Fix'.
You're asking the wrong guy. :-) If it were up to me this would never go through. So, yes, a solid -1 from me. If anything, I'm stronger against your "as" version than against C-style "=", (a) because the latter draws more attention to the assignment (I hate side effects buried deeply) and (b) because it's more familiar. The existing "as" syntaxes have a different purpose, they are top-level only so they cannot be deeply buried. But numerically I'd still be -1 on the "=" syntax too. I'm just throwing that preference for "=" out in case a future BDFL or someone forking the language wants to do it differently. -- --Guido van Rossum (home page: http://www.python.org/~guido/)
Jervis Whitley wrote:
if (something as x) == other: # can now use x.
Interesting. I'd definitely prefer that to the C-style inline assignment syntax: I think it reads better, and there's less chance of the Accidental Assignment Instead Of Comparison trap that has plagued other languages. I remain to be convinced that inline assignment is enough of a win in general, but if implemented, that's the syntax I'd want. -- And Clover mailto:and@doxdesk.com http://www.doxdesk.com/
On Sat, Mar 14, 2009 at 10:15 AM, And Clover <and-dev@doxdesk.com> wrote:
Jervis Whitley wrote:
if (something as x) == other: # can now use x.
Interesting. I'd definitely prefer that to the C-style inline assignment syntax: I think it reads better, and there's less chance of the Accidental Assignment Instead Of Comparison trap that has plagued other languages.
I remain to be convinced that inline assignment is enough of a win in general, but if implemented, that's the syntax I'd want.
Perhaps you want to replace top-level assignments with "expr as target" as well? -- --Guido van Rossum (home page: http://www.python.org/~guido/)
if (something as x) == other: # can now use x.
Interesting. I'd definitely prefer that to the C-style inline assignment syntax: I think it reads better, and there's less chance of the Accidental Assignment Instead Of Comparison trap that has plagued other languages.
However, allowing this "something as x" syntax for assignment would cause confusion with the "with contextmanager as x" scenario. "as" was chosen in their case because the expr contextmanager is not assigned to x. While I do like the "as" syntax too, I have not endorsed it for the above reason. However, this does show that using the "as" makes this somehow pythonic looking, and there must be an alternative that keeps this far enough away from the assignment expressions in other languages so as to avoid the trap you mention.
I remain to be convinced that inline assignment is enough of a win in general, but if implemented, that's the syntax I'd want.
Cheers, Jervis
Jervis Whitley wrote:
if (something as x) == other: # can now use x. Interesting. I'd definitely prefer that to the C-style inline assignment syntax: I think it reads better, and there's less chance of the Accidental Assignment Instead Of Comparison trap that has plagued other languages.
However, allowing this "something as x" syntax for assignment would cause confusion with the "with contextmanager as x" scenario. "as" was chosen in their case because the expr contextmanager is not assigned to x. While I do like the "as" syntax too, I have not endorsed it for the above reason.
If you look at the current uses for 'as' it is never for direct assignment: import x as y: 'x' is not a normal expression here, it's a reference into the module namespace. The value assigned to 'y' has nothing to do with what you would get if you evaluated the expression 'x' in the current namespace. with x as y: 'y' is assigned the value of x.__enter__(), not x except x as y: 'y' is assigned the value of a raised exception that meets the criteria "isinstance(y, x)". In all three cases, while the value eventually assigned to 'y' is *related* to the value of 'x' in some way, it isn't necessarily 'x' itself that is assigned (although the with statement version can sometimes give that impression, since many __enter__() methods finish with "return self"). Proposals for implicit assignment tend to founder on one of two objections: A. The proposal uses existing assignment syntax ('x = y') and runs afoul of the C embedded assignment ambiguity problem (i.e. did the programmer intentionally write "if x = y:" or did they actually mean to write "if x == y:"?) B. The proposal uses different assignment syntax ('x -> y', 'y <- x', 'x as y') and runs afoul of the question of why are there two forms of assignment statement? (Since any expression can be a statement, the new embedded assignment syntax would either work as a statement as well, or else a special rule would have to added to the compiler to say "cannot use embedded assignment expression as statement - use an assignment statement instead"). There are also a couple of more general points of confusion related to nested namespaces as far as embedded assignments go: 1. Assignments inside lambda expressions, list/dict/set comprehensions and generator expressions (all of which create their own local namespace) won't affect the current scope, but assignment in any other expression *will* affect the current scope. Just to make things even more confusing, assignments in the outermost iterator of a comprehension or genexp actually *will* affect the current scope. 2. Since global and nonlocal declarations only affect the current namespace, they're subject to the same kind of confusion as happens with local assignments: they won't affect assignments embedded inside lambda expressions, comprehensions and genexps (except for the outermost iterator for the latter two expression groups). With the way nested namespaces are set up, allowing embedded assignments would just be a recipe for long term confusion even if it did occasionally make some algorithms fractionally easier to write down. Cheers, Nick. Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------
With the way nested namespaces are set up, allowing embedded assignments would just be a recipe for long term confusion even if it did occasionally make some algorithms fractionally easier to write down.
Cheers, Nick.
Agreed. I wont be taking this argument any further. Could we close issue http://bugs.python.org/issue1714448? Cheers, Jervis
On Sun, Mar 15, 2009, Nick Coghlan wrote:
B. The proposal uses different assignment syntax ('x -> y', 'y <- x', 'x as y') and runs afoul of the question of why are there two forms of assignment statement? (Since any expression can be a statement, the new embedded assignment syntax would either work as a statement as well, or else a special rule would have to added to the compiler to say "cannot use embedded assignment expression as statement - use an assignment statement instead").
Just for the record, the most common different syntax suggested has historically been Pascal's ``:=`` -- Aahz (aahz@pythoncraft.com) <*> http://www.pythoncraft.com/ Adopt A Process -- stop killing all your children!
participants (8)
-
Aahz
-
And Clover
-
Carl Johnson
-
Greg Ewing
-
Guido van Rossum
-
Jervis Whitley
-
Nick Coghlan
-
Terry Reedy