On Fri, Apr 13, 2018 at 9:04 PM, Steven D'Aprano <st...@pearwood.info> wrote: > On Wed, Apr 11, 2018 at 03:32:04PM +1000, Chris Angelico wrote: > >> In any context where arbitrary Python expressions can be used, a **named >> expression** can appear. This can be parenthesized for clarity, and is of >> the form ``(target := expr)`` where ``expr`` is any valid Python expression, >> and ``target`` is any valid assignment target. > > Have we really decided on spelling this as `target := expression`? You > list this as a rejected spelling: > > >> 1. ``EXPR as NAME``, with or without parentheses:: >> >> stuff = [[f(x) as y, x/y] for x in range(5)] > > but I don't think the objections given should be fatal: > >> Omitting the parentheses in this form of the proposal introduces many >> syntactic ambiguities. Requiring them in all contexts leaves open the >> option to make them optional in specific situations where the syntax is >> unambiguous (cf generator expressions as sole parameters in function >> calls), but there is no plausible way to make them optional everywhere. >> >> With the parentheses, this becomes a viable option, with its own tradeoffs >> in syntactic ambiguity. Since ``EXPR as NAME`` already has meaning in >> ``except`` and ``with`` statements (with different semantics), this would >> create unnecessary confusion or require special-casing. > > The special casing you refer to would be to prohibit name binding > expressions in "except" and "with" statements. You should explicitly say > so in the PEP.
Parenthesis added to the rejection paragraph. > I don't think that prohibiting those two forms is a big loss. I think > any form of > > except (name := expression) as err: > do_something(name) > > is going to be contrived. Likewise for `with` statements. I agree as regards except statements. Not so much the with statements, though. How many times have people asked for "with (expr as name):" to be supported, allowing the statement to spread over multiple lines? With this syntax, it would suddenly be permitted - with dangerously similar semantics. For many MANY context managers, "with (expr as name):" would do the exact same thing as "with expr as name:". There is a general expectation that adding parentheses to an expression usually doesn't change the behaviour, and if it's legal, people will assume that the behaviour is the same. It isn't, and it's such a sneaky difference that I would call it a bug magnet. So if it's a bug magnet, what do we do? 1) Permit the subtly different semantics, and tell people to be careful 2) Forbid any use of "(expr as name)" in the header of a 'with' statement 3) Forbid it at top level, but permit it deeper down 4) Something else?? > I don't especially dislike := but I really think that putting the > expression first is a BIG win for readability. If that requires parens > to disambiguate it, so be it. There's a mild parallel between "(expr as name)" and other uses of 'as', which bind to that name. Every other use of 'as' is part of a special syntactic form ('import', 'with', and 'except'), but they do all bind to that name. (Point of interest: You can "with expr as x[0]:" but none of the other forms allow anything other than a simple name.) There's a strong parallel between "target := value" and "target = value"; in fact, the section on the differences is incredibly short and could become shorter. The only really important difference is that augmented assignment is not supported (you can't say "x +:= 5"), partly because it'd mean creating a boatload of three-character operators for very little value, and partly because augmented-assignment-as-expression is hard to explain. Which is better? A weak parallel or a strong one? How important is putting the expression first? On balance, I'm currently in favour of the := syntax, but it's only a small difference. > You also missed the "arrow assignment operator" from various languages, > including R: > > expression -> name > > (In an earlier post, I suggested R's other arrow operator, name <- expr, > but of course that already evaluates as unary minus expr.) I actually can't find anything about the -> operator, only the <- one. (Not that I looked very hard.) Is it a truly viable competitor, or just one that you'd like to see mentioned for completeness? > I think that there should be more attention paid to the idea of putting > the expression first, rather than the name. How many ways are there to bind a value to a name? Name last: * import x as y * from x import y as z * except x as y * with x as y Name first: * x = y * x += y # etc * for x in y * def x(.....) .... * def f(x=1) - arg defaults * class X: ... I'm seeing consistency here in that *EVERY* name binding where the name is at the end uses "as target" as its syntax. Everything else starts with the target, then defines what's being assigned to it. So I don't see much value in a "->" operator, except for the mere fact that it's different (and thus won't conflict in except/with); and the bulk of name bindings in Python put the name first. I don't have any really strong arguments in favour of :=, but I have a few weak ones and a few not quite so weak. So far, I have only weak arguments in favour of 'as'. ChrisA _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/