On Sun, Feb 14, 2021 at 11:23:59AM +0300, Paul Sokolovsky wrote: > > We've seen Paul mistake => for >= and he's not the only one. > > Well, my mistake is based on the fact that I don't spend high-level > neurons on remembering mundane low-level things, like order of > characters if the "greater or equals" operator. Instead, low-level > hands motor function neurons get it right when I type (most of the time > ;-)).
That would be just great if code was written more than it is read. ("Doesn't matter that people reading the code confusion the symbols, nobody reads it; what matters is that my hands know what to type.") Or if we had a rule that only Python developers with a minimum of 10 years experience are allowed to use it. [...] > > We already have chosen -> as the return type symbol in annotations, > > there is no ambiguity with also using it as the return value symbol. > > You're mastermind to claim it like that. I for one wasn't sure there's > no grammar-level ambiguity. If I'm wrong, I'm sure somebody will point that out. I'm not frightened of making bold claims that turn out to be wrong: that just means I have learned something new. (Or something old that I forgot.) My reasoning is this: The arrow return annotation in def functions is only legal outside of the parameter list, and if it is there at all, it must immediately follow the parameter list. def func(params) -> ret_expression: So any time you see a def with a parameter list, inside the parameter list any arrows have to be the arrow function syntax. The first arrow immediately following the parameter list must be the return annotation, and any arrows following that must be part of ret_expression which could of course include more arrow functions. No matter how complicated the parameter list gets, the parser will never expect that return annotation arrow until the parameter list has completed and the closing parenthesis has been seen. Even if it is an unreadable mess to the human reader, to the interpreter it ought to be completely unambiguous: until you hit that closing parenthesis, you're still in the parameter list and so no arrow can be the function annotation arrow. Am I right so far? Things get a bit more complex if the arrow functions themselves can include annotations. Lambdas don't, so perhaps these won't either. But if they do, I have assumed a syntax like this: (a:T, b:T, c:T -> T) -> body where the return type annotation is inside the bracketed argument list. Each of those "T"s are, naturally, arbitrary expressions, so they could also include arrow functions. But the parser can always tell if it is looking inside the parameter list, and if so, if it is a default value, an annotation, the return annotation, or if it has reached the end of the parameter list and is now in the body. And of course, nothing in the arrow function (not the parameter annotations, default values, the return annotation, or the body) can contain a def with its `->` arrow. So I am: - very confident that there is no ambiguity between def function return annotations and arrow functions if they don't include annotations (as lambdas do not); - not so confident if they do support annotations; - but in that case, it ought to be resolvable. There you go: I have boldly laid my neck out on the chopping block. If I am wrong, I will be happy to be corrected. > But there another problem, on humans' side. For humans, it's very > helpful when different concept look somewhat different. And it is also very helpful to have similar concepts look similar. Return a value? The critical term here is **return**. Return type? The critical term here is also **return**. > And it's very > helpful to use different arrows for values vs types. Why is it helpful? Helpful to whom? I can see that it would be helpful to have different arrows if there were cases where the reader wasn't sure whether they were looking at an annotation or an arrow function, but I don't think that will ever be the case. > > We could even allow both: > > > > (values:List[float], arg=0:int -> Type) -> expression > > I for one can't parse that (didn't have a morning coffee, but suspect > there's a typo/thinko). Yes, I swapped the order of the default value and the type annotation, it should read: (values:List[float], arg:int=0 -> Type) -> expression Sorry for the confusion. In case anyone is still having trouble parsing that: # lambda version lambda values, arg=0: expression # becomes arrow function (values, arg=0) -> expression # add parameter annotations (values:List[float], arg:int=0) -> expression # and the return type of the function body (expression) (values:List[float], arg:int=0 -> T) -> expression > Btw, I'm not sure about function values, but > IMHO, type notation should always use parens for arguments, e.g. "(int) > -> int". What is this type notation you are talking about, and how is it relevant to Python and this proposal? > > There are plenty of popular and influential languages that use the > > single line arrow -> such as Maple, Haskell, Julia, CoffeeScript, > > Erlang and Groovy, to say nothing of numerous lesser known and > > obscure languages. > > The question is how many of those language have first-class type > literals, and how many use the same notation for function literals and > type literals. I don't think that question either makes sense or is important. We are not limited to "type literals", whatever that means to you. (To me, that would mean built-in reserved words for types, like `integer`, `real`, `boolean` in Pascal.) Types can be expressions, like `List[object]` or `Union[Spam, Eggs]`. -- Steve _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/C6L2KCBYNTXSZ557G3YSILTNKGJEXLC3/ Code of Conduct: http://python.org/psf/codeofconduct/