On Jun 17, 2019, at 13:09, Guido van Rossum <guido@python.org> wrote:

On Mon, Jun 17, 2019 at 12:54 PM Andrew Barnert <abarnert@yahoo.com> wrote:
On Jun 17, 2019, at 07:47, Guido van Rossum <guido@python.org> wrote:

On Mon, Jun 17, 2019 at 7:23 AM Rhodri James <rhodri@kynesim.co.uk> wrote:
On 16/06/2019 03:34, Guido van Rossum wrote:
> I don't actually know how viable this proposal is, but given that it's
> being debated at some length, I'd like to put in my  opinion that *if*
> we're going to define an operator that's (roughly) synonymous with
> issubclass(), it should be '<:', which is used in other languages (e.g.
> Scala) and notational systems (https://en.wikipedia.org/wiki/Subtyping).
> Overloading '<=' would be easier to implement, but would also cause enough
> confusion that I think we should avoid it at all cost.

I rather strongly disagree.  We are describing a fairly standard
incomplete ordering, which makes the comparison operators completely
appropriate.  Adding new syntax for something that doesn't need it is
the thing likely to cause confusion.

Indeed it would work the same way as set comparison does, if you interpret a type as the set of its instances.

But I imagine that many Python users are not so familiar with this abstraction level (even if they use isinstance() and issubclass() all day long). Sometimes using a *different* operator is helpful to send a signal to the reader that a *different* kind of thing is being manipulated -- sort of like how you can tell that a collection is a list or a set by noticing whether values are added using append() or add().

Type theorists apparently have chosen to use the <: notation, and presumably for the same reason.

Theoretical, and Scala (and Haskell, C++, etc.), types are a different kind of thing from objects, meta-objects that can only be used in special meta-level computation, so using a different operator makes sense. It’s like using |- rather than -> in proofs in basic logic.

I'm not sure I agree. You can't compare numbers and strings in Python 3, but we happily use + and <= for both. So the argument that different kinds of objects need different operators feels like it doesn't get to the heart of the matter here.

In Python, Integers, strings, and types are different _types_ of object, but they’re all the same _kind_. There’s just one syntax and one set of evaluation rules that apply to all types of values, including types themselves.

That’s what’s different from Scala, etc., where types are not the same kind of thing as values, and <: isn’t an operator on values that can be overloaded by the type, but a piece of special syntax used in completely different parts of the language grammar that only operate on types.

Sure, completely different syntax doesn’t absolutely require different spelling (see [] for indexing and specialization in Scala, or : in dict displays and compound statements in Python), but it usually implies it, at least as a default.

And sure, you can always add new operators as syntactic sugar even when they aren’t necessary, but it’s only occasionally a good idea.

In short, the key is that isinstance(type, type) is not even well-formed in type theory, but in Python, it’s guaranteed true.[1]

Is this any more bizarre than that s[0] == s[0][0] for any non-empty Python string?

Lots of things are different between Python and Scala, and most of them are not bizarre. But that doesn’t mean they don’t have natural consequences. Variables not being lvalues isn’t bizarre, but it does imply, e.g., no equivalent to C++ operator=. And type being a type isn’t bizarre, but it does imply no need for separate syntax for type computation.

Sure, most people who want to write type-computation expressions often enough that they need operators, and who are familiar with the abstraction of types as sets, will be people who are familiar with type theory or Scala or Rank-N Haskell or whatever, and are likely to be more comfortable with <: syntax. And there’s already some special syntax for type-level computation (the class statement), so it’s not like it would be unprecedented. But most such people will also be sophisticated enough to avoid confusion when using <. And to write their own metaclass that defines __lt__ if they need it (or at least fetch one from PyPI and use it). Also. I think we’re talking about something only a smallish number of people will ever want to do, and then only pretty rarely, in the first place.

So I don’t think anything needs to be changed at all.

That's where I started. I also provided an argument that *if* something needs to be changed it should *not* be to introduce <= for types.

I agree that <= is not as good a spelling as <: for subclass. But I don’t think it’s that bad; it’s more than good enough for the rare cases where someone needs so much type comparison that they need operators. Especially since it already works today (with a simple metaclass). But even if it is worth adding an operator to type, I think it’s still likely not worth making it a new operator with a new dunder and so on.

[1] Technically, 

Right. This seems immaterial to the discussion (looks like you've been nerd-sniped :-).

Well, there’s a reason it’s buried in a footnote. I didn’t think you really wanted to discuss type theory; even though you brought it up. But just in case… :)