One reason for why PEP 677 was rejected, was that the syntax required backtracking in the parser. The SC recommended:
When proposing a syntax change, low complexity is better. While not always possible, it’s ideal if it could still be described using our old <=3.8 parser. It is important to have in mind that adding syntax that only our modern PEG parser can handle could lead to greater cognitive load and external tooling implementation costs.
This was the proposed syntax:
def flat_map(
func: (int) -> list[int],
l: list[int]
) -> list[int]:
out = []
for element in l:
out.extend(f(element))
return out
But the PEP also mentions another syntax in the Rejected alternatives: Hybrid keyword-arrow Syntax:
def flat_map(
func: def (int) -> list[int],
l: list[int]
) -> list[int]: ...
i.e., def
is added as a keyword introducing the callable.
I think this would be parsable with the old parser (def
is now allowed at the beginning of any expression but will throw an error if not followed by (
).
This should also be allowed:
type StrTransform = def (str) -> str
Returning a callable:
def f() -> def (int, str) -> bool:
pass
I admit this looks a bit confusing at first, but I think you’d get used to it quickly. (I think it’s less confusing than the original PEP 677, actually.)
The main objection in the PEP was this:
But we think this might confuse readers into thinking
def (A, B) -> C
is a lambda, particularly because Javascript’sfunction
keyword is used in both named and anonymous functions.
I agree that this is may be a problem, but it should help that this syntax will only appear in type annotations, so it should be clear from context that it’s not a lambda.
Generally, I’d expect someone who knows Python but doesn’t use type annotations to understand this:
def flat_map(
func: def (int) -> list[int],
l: list[int]
) -> list[int]: ...
much easier than this:
def flat_map(
func: Callable[[int], list[int]],
l: list[int]
) -> list[int]: ...
All the other advantages of PEP 677 remain, like the nicer Concatenate
syntax:
f5: def (int, **P) -> bool
f5: Callable[Concatenate[int, P], bool]