Response inline

Le jeu. 19 sept. 2019 à 19:18, Andrew Barnert <abarn...@yahoo.com> a écrit :

> Steven already answered many of these, so I’ll just snip the ones he
> didn’t.
>
> On Sep 19, 2019, at 00:03, Philippe Prados <philippe.pra...@gmail.com>
> wrote:
>
>
>  * The static types in typing are not instances of type, so you need to
> work out what to do with them.
> I do not understand the remark. My patch of 'mypy' accept this new syntax.
>
>
> If you’re only adding __or__ to type, then List[int] | Tuple[int] is still
> an exception.
>
You are right. You find a bug in my current implementation.
I add __or__, __ror__ and __invert__ in _GenericAlias and published the new
version.
Now,
assert List[int] | Tuple[int] == Union[List[int], Tuple[int]]

>
>  * Making isinstance work isn’t a matter of accepting new syntax as you
> suggest, but making the values already created by the existing syntax
> work—and, since this appear to have been deliberated removed in 3.6, you
> need to explain why this was a mistake and should be undone. (Have you
> uncovered the reason for this change?) And whether it should affect just
> Union or other types.
> Where I can find the argument to explain why this have been deliberated
> removed in 3.6 ?
> In my implementation, they affect just Union. isinstance() can now accept
> type, Tuple or Union.
>
>
> If isinstahce(2, List) is still a TypeError, then what happens with 
> isinstance(2,
> List|Tuple)? Probably it should raise a TypeError complaining that List
> can’t be used in type checks, like isinstance(2, List) does?
>
Now,
assert isinstance(2, List|Tuple) == False
assert isinstance(2, List|int) == True
assert isinstance(2, List) == False
assert isinstance(2, ~int) == True
assert isinstance(None, ~int) == True

>
>  * What about except clauses? Shouldn’t they take unions if isinstance
> does? How does that work?
> Good question. To accept `except TypeError | ZeroDivisionError:` in place
> of `except (TypeError, ZeroDivisionError):`, the impact is bigger, but
> why not ?
>
>
> As Steven pointed out, the syntax will already handle this, but you do
> need to change the implementation of how exceptions check for a matching
> except spec while looking for a handler. I’m guessing it’ll be easy, but I
> haven’t looked at that code in a long time.
>
I think so too

>
>  * Should you be able to test whether List or List[int] is a subclass if
> List|Tuple or List[int]|Tuple[int]? If so, that reverses even more of the
> 3.6 change, and then you have to explain why you can’t use
> issubclass(List[int], Iterable[int]) or issubclass(List[Integral],
> List[int]) but can use this. If not, what’s the use case for issubclass
> with unions in the first place?
> It's a question for "typing". My proposition change nothing about that.
>
>
> No, typing avoids having to make this decision, because these aren’t
> types, and can’t be used in issubclass at all. If you’re changing that some
> these are now legal calls, you have to decide which ones, and what those
> calls return.
>
I fix this

>
>  * You will probably want to create a new builtin type for unions, rather
> than having a bunch of different parts of the Python core import from
> typing.
> May be.
>
>
>  * In addition to other benefits, someone (Stephen?) pointed out that
> builtin support could mean that, e.g., isinstance(3, int|str) could be just
> as efficient as isinstance(3, (int,str)), which alleviated multiple
> people’s concerns. Is that’s part of the proposal you should make that
> point; if not, explain why not.
> The implementation use the tuple present in the Union type. The impact is
> just to check the type of the second parameter and replace it with the
> tuple from the Union.
>
>
> If you have to do an instance check against a type with a subclass hook,
> and that you have to import first, on every call to find out whether the
> second parameter is a Union, that will slow down every isinstance call. And
> if you then have to get the tuple out of the instance dict, that could make
> unions significantly slower than tuples.
>
It's why at this time, I use a trick

if (!strcmp(Py_TYPE(cls)->tp_name,"_GenericAlias"))

I am sure, the implementation may be better. With using the macro
PyType_FastSubclass() ?

>
> Checking a value against a built in type and accessing a member out of a C
> struct are a lot faster
>
> It’s possible that neither of those will affect performance enough to
> matter, but you’d have to benchmark it to prove that.
>
>  * Mentioning the wide variety of other languages’ typing systems that use
> | for related features would probably make it more compelling.
> I find only Scala now.
>
>
> The way you build sum types in ML and most languages derived or inspired
> by it (from Haskell to Swift) is with the | operator.
>
> Most of those languages sum types give optional or mandatory constructor
> names to the alternatives, so it’s not quite the same thing as anonymous
> unions:
>
>     IntStr = Int int | Str str
>
> … this is a type whose values are an int or a str, but the way you
> construct one is with Int(2) or Str("a"), not with IntStr(2). And the way
> you extract the values is not by explicitly type-checking, but by pattern
> matching using | again, against the constructor names, something like this
> Int(n): Int(n*2) | Str(s): Str(f"{s} doubled")
>
> For a more anonymous union, you usually use an explicit union or either or
> similar type: Either[int, str] gives you a type whose values are either an
> int or a str, and you access them with the Left and Right constructors from
> Either rather than specific named ones.
>
> They could have syntactic sugar so that int|str means Either[int, str], it
> just doesn’t come up often enough—except the special case of Either[Error,
> X], which in some languages is the main way to do error handling. So if
> they do add any sugar, it’s usually for that special case, not the general
> one.
>
> So you can see how this is all related to anonymous union types but not
> identical.
>
> Scala is the exception here, but that’s because Scala has anonymous Union
> and Either as separate types, where Union means least upper bound on the
> lattice while Either is the direct one-or-the-other-and-nothing-else like
> Python’s Union. (And it’s the former rather than the latter that gets | for
> shorthand.(
>
> The similarity is a lot like Python’s implicit Optional vs. the explicit
> Optional in other languages, where you construct an Optional[int] as a
> constructor call to Nothing() or Just(3) and then extract the value with
> pattern matching. Most of these languages have added a variety of kinds of
> syntactic sugar because it’s so common, so, e.g., something like x? means
> Optional[x], and ?x gives you a bool that says whether x is a non-empty
> value and !x means a pattern match on Just(x) and throw if it fails, and if
> let val = x: stuff is further shorthand for if ?x: val = !x; stuff and so
> on. None of this is identical to proposing ~int to mean Optional[int], but
> it’s all clearly similar, and shows how many languages have found it worth
> having shorthand like this.
>
> So it’s the same with |. No language does something identical to what
> you’re proposing, but lots of languages do something similar and related.
>
> One more thing:
>
> In fact, having the two versions both ready could help clarify the
>> discussion about PEP 585, and more generally about the advantages and
>> disadvantages of going more toward a “two-kinded” type system vs. leaning
>> more into “everything is first-class”.
>>
>
> I don’t think this was very clear, so apologies.
>
> In lots of languages (Scala, Haskell, Swift, even C++) there’s syntax for
> operating on types, but it’s separate from the syntax for operating on
> values. PEP 585 is a step in that direction—the syntax of annotations is
> still the syntax of expressions, but the semantics are different (they just
> aren’t fully evaluated at all). That means you can put forward references
> in an annotation without getting a NameError. And it means you could define
> int|str as valid in annotations, without making it valid at runtime. This
> would avoid all the hard decisions and optimization issues, and it would be
> a lot closer to what Scala does, and it could even open the door for things
> like using the | operator for related but different meanings in type
> expressions and value expressions (e.g., the way ? means Optional in a type
> expression but optional-chaining in a value expression in Swift).
>
> On the other hand, in Python, everything is a first-class value, including
> types, and everything that types do (constructing objects, type checks,
> even metaclass stuff) is determined by the normal language syntax and
> semantics operating on types as values. There are a lot of benefits to
> that. Which is probably why everyone who uses Python naturally expects that
> if int|str is a thing, it’ll be a thing you can pass around at runtime and
> use in isinstance and so on, even if that makes the language and the
> implementation a little more complicated and they don’t have a compelling
> use in mind for it.
>
> I haven’t followed the discussion around PEP 585, but I suspect that when
> you take this PEP to the typing-sig people, these questions are going to be
> more relevant to them than the bikeshedding stuff about how to spell ~ and
> how other languages spell it. But I could be wrong.
>
Thanks, it more clear for me
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/I634ENKFHG5OEJAMPHKXCWBEJRKVBE6Y/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to