
On Wed, Feb 28, 2018 at 8:04 PM, Robert Vanden Eynde <robertve92@gmail.com> wrote:
Considering the 3rd syntax : '(' EXPR 'with' NAME '=' EXPR ')'
Wouldn't have the problem of "execution being middle first and would clearly differenciate the "with NAME = CONTEXT" from the "with CONTEXT as NAME:" statement.
It's still right-to-left, which is as bad as middle-outward once you combine it with normal left-to-right evaluation. Python has very little of this, and usually only in contexts where you wouldn't have much code on the left:
def d(): ... print("Getting dictionary") ... return {} ... def k(): ... print("Getting key") ... return "spam" ... def v(): ... print("Getting value") ... return 42 ... d()[k()] = v() Getting value Getting dictionary Getting key
Python executes the RHS of an assignment statement before the LHS, but the LHS is usually going to be so simple that you don't really care (or even notice, usually). By creating a name binding on the right and then evaluating the left, you create a complicated evaluation order that *will* have complex code on the left.
Considering the PEP :
1) I think I spoke too fast for SqlAlchemy using "where", after looking up, they use "filter" (I was pretty sure I read it somewhere...)
There's something with "select where exists" that uses .where(). It may not be as common as filter, but it's certainly out there.
2) talking about the implementation of thektulu in the "where =" part.
?
3) "C problem that an equals sign in an expression can now create a name binding, rather than performing a comparison." The "=" does variable assignement already, and there is no grammar problem of "=" vs "==" because the "with" keyword is used in the expression, therefore "with a == ..." is a SyntaxError whereas "where a = ..." is alright (See grammar in thektulu implemention of "where").
Yes, but in Python, "=" does variable assignment *as a statement*. In C, you can do this: while (ch = getch()) do_something_with(ch) That's an assignment in an arbitrary condition, and that's a bug magnet. You cannot do that in Python. You cannot simply miss out one equals sign and have legal code that does what you don't want. With my proposed syntax, you'll be able to do this: while (getch() as ch): ... There's no way that you could accidentally write this when you really wanted to compare against the character. With yours, I'm not sure whether it handles a 'while' loop at all, but if it does, it would be something like: while (ch with ch = getch()): ... which doesn't read very well, doesn't really save much, but yes, I agree, it isn't going to accidentally assign.
Remember that the lexer knows the difference between "=" and "==", so those two are clearly different tokens.
It's not the lexer I'm worried about :)
4) Would the syntax be allowed after the "for" in a list comprehension ?
[[y, y] for x in range(5) with y = x+1]
This is exactly the same as "for y in [ x+1 ]", allowing the syntax here would allow adding "if" to filter in the list comp using the new Variable.
[[y, y] for x in range(5) with y = x+1 if y % 2 == 0]
I honestly don't know. With my "as" syntax, you would be able to, because it's simply first-use. The (expr as name) unit is itself an expression with a value. The 'with' clause has to bracket the value in some way.
5) Any expression vs "post for" only
When I say "any expression" I mean:
print(y+2 with y = x+1)
When I say "post for in list comp" I mean the previous paragraph:
[y+2 for x in range(5) with y = x+1]
Allowing both cases leads to having two ways in the simple case [(y,y) with y = x+1 for x in range(5)] vs [(y,y) for x in range(5) with y = x+1] (but that's alright)
Allowing "any expression" would result in having two ways to have variable assignement :
y = x + 1 print(y+2)
Vs:
print(y+2 with y = x+1)
One could argue the first is imperative programming whereas the second is Functional programming.
The second case will have to have "y" being a Local variable as the new Variable in list comp are not in the outside scope.
I don't know what the benefit is here, but sure. As long as the grammar is unambiguous, I don't see any particular reason to reject this.
6) with your syntax, how does the simple case work (y+2 with y = x+1) ?
Would you write ((x+1 as y) + 2) ? That's very unclear where the variable are defined, in the [(x+1 as y), y] case, the scoping would suggest the "y" Variable is defined between the parenthesis whereas [x+1 as y, y] is not symmetric.
What simple case? The case where you only use the variable once? I'd write it like this: (x + 1) + 2
The issue is not only about reusing variable.
If you aren't using the variable multiple times, there's no point giving it a name. Unless I'm missing something here?
7) the "lambda example", the "v" variable can be renamed "y" to be consistent with the other examples.
Oops, thanks, fixed.
8) there are two ways of using a lamba, either positional args, either keyword arguments, writing
(lambda y: [y, y])(x+1)
Vs
(lambda y: [y, y])(y=x+1)
In the second example, the y = x+1 is explicit.
Ewww. Remind me what the benefit is of writing the variable name that many times? "Explicit" doesn't mean "utterly verbose".
10) Chaining, in the case of the "with =", in thektulu, parenthesis were mandatory:
print((z+3 with z = y+2) with y = x+2)
What happens when the parenthesis are dropped ?
print(z+3 with y = x+2 with z = y+2)
Vs
print(z+3 with y = x+2 with z = y+2)
I prefer the first one be cause it's in the same order as the "post for"
[z + 3 for y in [ x+2 ] for z in [ y+2 ]]
With my proposal, the parens are simply mandatory. Extending this to make them optional can come later.
11) Scoping, in the case of the "with =" syntax, I think the parenthesis introduce a scope :
print(y + (y+1 where y = 2))
Would raise a SyntaxError, it's probably better for the variable beeing local and not in the current function (that would be a mess).
Remember that in list comp, the variable is not leaked :
x = 5 stuff = [y+2 for y in [x+1] print(y) # SyntaxError
Scoping is a fundamental part of both my proposal and the others I've seen here. (BTW, that would be a NameError, not a SyntaxError; it's perfectly legal to ask for the name 'y', it just hasn't been given any value.) By my definition, the variable is locked to the statement that created it, even if that's a compound statement. By the definition of a "(expr given var = expr)" proposal, it would be locked to that single expression. ChrisA