Rust uses "extends" *and* a colon? (I think I get it -- it uses the colon but you can also use a "where" clause.)
Yeah in Rust `fn fun<T: Sized>(a: T) {}` is syntactic sugar over fn fun<T>(a: T) where T: Sized {} where clauses are actually incredibly powerful, but as Eric points out, they probably wouldn't work well for Python. class Example[T] # () would go here?? where T: int: ... def foo[B](b: B) -> B where B: int: ... Though now that I've written these examples this actually doesn't look too terrible? Maybe I just have used Rust too much recently :) Anyway, to the issue at hand, I expect people will be confused if we do T(int), for example, consider this declaration: class Bar[T(int)](Baz[T]): ... That's a *lot* of brackets and parentheses in a small amount of space, and it makes it harder to find an unbalanced bracket or parenthesis. I also don't particularly like <:. While it is used in type theory papers and Scala, most people that use types have read neither of those, and it will be unfamiliar. I think the utility of lower bounds is probably unlikely to be worth their introduction (though perhaps someone has a use case I haven't thought of!), so I feel that the colon syntax is the best candidate: it is familiar, and it is the easiest to read, which is of course a matter of opinion, but perhaps it would be good to do a poll about this? On Sat, Jul 2, 2022 at 7:38 PM Guido van Rossum <guido@python.org> wrote:
On Fri, Jul 1, 2022 at 7:20 PM Eric Traut <eric@traut.com> wrote:
It's a bit different though in that the type parameter's bound is not the type of the variable
I don't think it's different. When you annotate a function parameter with `Foo`, you are not saying that the type must be a `Foo` object at runtime. Rather, you're saying that the parameter is constrained to a type that is compatible with `Foo` — i.e. a subtype thereof.
It's the same logic with the upper bound for a type parameter. When you say that it is bounded by `Foo`, you are not saying that it is type `Foo`, but rather that its type is constrained by `Foo` — i.e. it must be a subtype thereof.
I think Jelle is talking about the type of the thing before the colon in relation to the thing after the colon. When you say 'T: int' in a type parameter clause, that means roughly 'issubclass(T, int)'. But when you write 'a: int' in a parameter list, that means 'isinstance(a, int)'.
However, I'm not convinced this is a big enough problem to reject ':' outright.
I'm not completely opposed to using `<:` like in Scala, but I don't think most Python users will have ever seen (or heard of) Scala, so this token will seem very foreign to them. Also, I don't think it works well with constrained type parameters.
I've seen this used in papers about static types as well, without introduction, so apparently it's a standard operator in that community ("Consider types *T* and *S* s.t. *T* <: *S* ... etc.). However, it's always taken me a bit of thinking about the context to derive that '<:' means "subclass" (i.e., "extends") and not "superclass".
To inform this discussion, I've updated the draft PEP to include an "Appendix A: Survey of Type Parameter Syntax". Here's a direct link: https://github.com/erictraut/peps/blob/typeparams/pep-9999.rst#appendix-a-su...
That link no longer works (probably because I merged the PR :-). Here's a working link: https://github.com/python/peps/blob/main/pep-0695.rst#appendix-a-survey-of-t...
I looked at C++, Java, C#, TypeScript, Scala, Swift, Rust, Kotlin, and Julia.
There are four patterns that emerge for specifying constraints on a type parameter: 1. Java and TypeScript use the "extends" keyword 2. C# and Rust use the "where" keyword (and place the clause at the end of the declaration — something that wouldn't work well for Python's grammar) 3. Scala and Julia use the "<:" operator 4. Swift, Rust and Kotlin use a colon
Rust uses "extends" *and* a colon? (I think I get it -- it uses the colon but you can also use a "where" clause.)
If we think that we will want to support a lower bound at some point in the future, that would argue in favor of "<:" because ">:" is the logical counterpart. However, I don't think there's a strong need for specifying a lower bound, and most languages forego this capability. For that reason, I still favor using a colon here.
The call-like syntax also easily accommodates this: just add a new keyword parameter 'lower_bound=...'.
Note that none of these languages use a function call or constructor-like syntax. Adopting that approach would make Python an outlier among all other popular languages.
Not that we care all that much about that (none of them use indentation either :-).
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-c...> _______________________________________________ Typing-sig mailing list -- typing-sig@python.org To unsubscribe send an email to typing-sig-leave@python.org https://mail.python.org/mailman3/lists/typing-sig.python.org/ Member address: ethan@ethanhs.me