-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
PEP 677: Callable Type Syntax #2187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Initial commit of a draft Callable Type Syntax PEP, ported from a google doc at https://docs.google.com/document/d/16UmBItZWIzKZK3ZTpDKH8vazNZ817E4UqKmPtebO4jQ/edit
AlexWaygood
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some thoughts
Thanks @AlexWaygood for catching at least a half-dozen typos! Co-authored-by: Alex Waygood <[email protected]>
AlexWaygood
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A little more sub-editing 🙂
Co-authored-by: Alex Waygood <[email protected]>
Co-authored-by: Alex Waygood <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more things I spotted! Some of these are more elegance-of-writing points 🙂
Co-authored-by: Alex Waygood <[email protected]>
AlexWaygood
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is my final pass 😄 it's a great PEP, I'm rooting for it!
This is based on Pradeep's feedback that we were getting to the point too abruptly. The quality is probably lower than the rest of the PEP because this new writing hasn't yet had any edits or proofreading. Also, since I was rewriting this section anyway I went ahead and formatted it as 80 columns instead of infinite-width. The whole file eventually needs to be reformatted but this one section was blocking me (it was infinite width because it started as a google doc, but using a text editor this is not so good)
Co-authored-by: Alex Waygood <[email protected]>
I wrote a google doc describing this idea in more detail so that anyone not familiar with it can get context without it taking up over a page of the PEP itself. We could potentially inline that entire discussion, but I think having a separate doc is probably better because it might trigger a discussion of proposing that idea that isn't directly relevant to callable type syntax. I also added some subsubsection headers to keep this subsection organized.
50975e4 to
ba0b50f
Compare
ce8c821 to
0cdb7e0
Compare
c6aea80 to
296c51f
Compare
|
I think I fixed most of the build issues. It's unhappy with the header, and I'm lost - as far as I can tell, I pasted the formatting exactly from an existing pep, and checked it against a few others. But it complains about indentation and block quotes on almost every line, starting with my name. |
|
Can you address Jelle's change request? |
|
I think I addressed the comments already. I'm not sure how to tell github about it though (and I accidentally requested re-review while I was trying to figure it out, which I didn't intend to do). The docs say there's a way to "dismiss review" once you've addressed comments but I cannot see that option. Maybe I don't have the right permissions? |
|
@gvanrossum do you want to do another round of review? If not I can merge the PR once CI is green and I can't find any more typos. @stroxler I think you put the "in the" typo back at least once, let me check if it's still there. |
|
IIRC you leave a comment saying |
|
I have made the requested changes |
|
I dunno. I'll skim the thing one more time and then land it regardless. |
|
(FYI, "I have made the requested changes" triggers the Bedevere bot on the CPython repo but it doesn't do anything on GiitHub in general.) |
|
Awesome, thanks @JelleZijlstra and @gvanrossum! If readability PRs later on are a problem then it may be worth waiting until @pradeep90 has another go at the Motivation section, it's new and I think we'll want to reword it. But if that's not a problem I'd prefer to land and send to python-dev, I think the sections they'll care about should be ready once you've reread them. |
|
Later PRs are fine, I'm happy to review them. Let's just land this before somebody else grabs our number. :) |
gvanrossum
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Despite various comments I'm going to land this, after fixing only one definite markup bug.
| The use of ``**P`` for supporting PEP 612 ``ParamSpec`` rules out any | ||
| future proposal using a bare ``**<some_type>`` to type | ||
| ``kwargs``. This seems acceptable because: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm. Occasionally we hear from someone who has a TypedDict that they want to use as the type for some function's kwargs. If we wanted to support that for a function type's kwargs we'd be hosed -- the obvious notation would be (**TD) -> bool. Or maybe that would just work, and what you're ruling out here is use of (**int) -> bool to type e.g. def f(**args: int) -> bool: ...?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... Technically, there is nothing to prevent us from supporting **KwargsTypedDict (or even **int) in the future. Type checkers could distinguish **KwargsTypedDict and **P based on the actual values of the variables.
The main reason we have **P instead of a bare P is to make it syntactically obvious that it is a ParamSpec (like Callable[P, R]). Otherwise, users might have trouble realizing that P is a ParamSpec in (Foo, P) -> int.
We could update the PEP (in a new PR) saying that it is actually forward-compatible with both **KwargsTypedDict and **int.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm on the fence about this. Technically, there's nothing prevent us from using **<some_type> with divergent semantics depending on the information contained within <some_type>, type-checkers could handle this.
But it would be pretty unusual for python to let the semantics of the same syntax vary that much - a ParamSpec is a pretty different concept from typing the kwarg variadic argument.
My guess is that, in an extended syntax, we would work around this by requiring names for the vararg and kwarg,
so that we would use:
(**kwags: int) -> bool
(**kwargs: **MyTypedDict) -> bool
I think we should update the PEP to clarify that it's technically still possible to use **int and **MyTypedDict but I don't want to imply this is a good idea or say anything that's likely to prompt much discussion of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For what it's worth, I don't see the issue with allowing **MyTypedDict in the future: just like **P, it means "this is the type for all of the kwargs". Perhaps to keep this option open we should avoid using the name "paramspec" in the AST and runtime objects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it would be pretty unusual for python to let the semantics of the same syntax vary that much
Would it, though? We have 1+2 == 3, vs "a" + "b" == "ab". We have a[i] (indexing list or tuple) vs. d[key] (lookup in dict or mapping) vs. list[int] (generic type). Etc. So I think there are enough precedents -- we don't need to worry about this looking odd.
| community decides after more experience and discussion that we want | ||
| the additional features, they should be straightforward to propose | ||
| in the future. | ||
| - We realized that because of overloads, it is not possible to replace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if "because of overloads" requires a complete example (e.g. an overloaded function, the observation that its type can't be expressed using current function types, and the conclusion that it must be done using a Callback Protocol). It might also be useful to explain why you can't just replace the overload with a union of function types. (Hm. Why couldn't you?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on a concrete example.
It might also be useful to explain why you can't just replace the overload with a union of function types. (Hm. Why couldn't you?)
Overloads correspond more to an intersection of callable types. If we had a union f: (int) -> str | ((list[int]) -> None), then we wouldn't be able to pass an argument to just one of the union items: f(42) would error because it's not a list[int]; f([1, 2]) would error because it's not an int.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- No replacement for callback protocol:
| (Int, String) => Bool | ||
|
|
||
| Scala, like Python, has the ability to provide function arguments by name. | ||
| Funciton types can optionally include names, for example:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Funciton types can optionally include names, for example:: | |
| Function types can optionally include names, for example:: |
|
Congrats! I wish all PEP authors were like you. :-) |
| **Pradeep** `brought this proposal to python-dev | ||
| <https://mail.python.org/archives/list/[email protected]/thread/VBHJOS3LOXGVU6I4FABM6DKHH65GGCUB>`_ | ||
| for feedback. | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A Usage Statistics section would be good to describe the methods, projects, and limitations. We could link to it from other parts of the PEP.
The draft of our Callable Type Syntax PEP is in a complete enough state that it is worth moving discussion to github so we have a history of major revisions going forward.
There are still many edits coming and we do not yet have a PEP number, hence keeping this as a draft PR.
Currently open problems (as of December 9) that I plan to get to soon: