Making functions subscriptable at runtime

This is offtopic here, but I think that it is better to make it a callable rather than a subscroptable: callable_type(some_func). Then it could be used as a decorator:

@callable_type
def MyCallableType(a: int, /, b:str, *, c: float = 0) -> bool:
    ...

If we don’t care about the names of the positional arguments, we should make them positional-only.

That proposal is made obsolete by PEP 695.

4 Likes

Just curious, why is this still being discussed? Hasn’t PEP 695 already been approved for being added in Python 3.12?

Because PEP 695 does not propose making functions subscriptable at runtime

4 Likes

I’ve written up the first draft of this idea as a PEP. Any thoughts and feedback would be greatly appreciated (as would a sponsor :wink:)

Thanks.

7 Likes

I will sponsor the PEP.

3 Likes

That looks pretty promising! I find the examples in the “Motivation” section pretty convincing. A few thoughts right off the bat:

  • You use the term “bidirectional inference” in the second sentence, which is quite type-theory-jargon-y. It would be good to use less jargony language or explain what the jargon means or link to a definition of the term. (Mypy also more often refers to this concept as “type context” in their documentation/codebase.)
  • You refer to Unknown several times, which is a pyright-specific concept. It would be better to say something like “type checker cannot infer the type of T” instead of “revealed type is list[Unknown]” – then it can apply to all type checkers equally
  • You say “This proposal also opens the door for runtime reflection of type parameters similar to Rust, C++ and Scala.” Discussing those concepts would be beyond the scope of the PEP, I think, but it might be good to link to an explanation of what you’re referring to here.

I’m also happy to sponsor :slight_smile:

3 Likes

I would also happily sponsor.

I note that Mojo is adopting this syntax as well.

2 Likes

Another piece of feedback: this is one of the motivating examples in the PEP:

def make_list[T](*args: T) -> list[T]: ...
reveal_type(make_list())  # ??

It might be worth noting explicitly that type checkers should be able to infer the type here if an explicit annotation is given as the “expected type” for the returned object, e.g.:

def make_list[T](*args: T) -> list[T]: ...
x: list[int] = make_list()
reveal_type(x)  # list[int]

There are drawbacks to this solution: it forces users to split expressions into multiple parts, making code unnecessarily verbose. But it would be good to explicitly state in the PEP what the current solution is, and why it’s insufficient; situations where it won’t suffice, etc.

1 Like

Thanks for all the pointers Alex

1 Like

Thank you Jelle, Alex and Guido for offering to sponsor the PEP, you’re really spoiling me for choice after consulting random.choice I’m happy to say I’m picking Guido to sponsor the PEP.

2 Likes

Okay. I hope that Jelle an Alex will continue to provide high quality detailed feedback on the PEP! Do you know the next steps?

Rewrite the PEP in rst add the appropriate headings and make a PR to python/peps?

6 Likes

Yup that’s it.