Update: Work on Optional Syntax PEP
Hi there, Recently I have been working on an implementation for PEP 604 (https://www.python.org/dev/peps/pep-0604/). While working on this, I started reviewing and exploring what new Optional syntax would look like in the Python language. I've written a rough draft of a PEP and wanted to present it to this email list before submitting a PR. I know this is a topic that has been discussed in many settings (Github issues, in person typing meetups, etc. )previously, and wanted to solicit feedback here first. Let me know if submitting a PR would be a better way to gauge sentiment and feedback on this proposal. Draft Proposal (branch compare): https://github.com/python/peps/compare/master...MaggieMoss:optional-syntax-p... Gist: https://gist.github.com/MaggieMoss/c848cb3a581979f445d075c15629c950 Thanks again, Maggie
Wow, you've been busy! (I know I still owe you a review on the PEP 604
implementation. It's on my TODO list. :-)
My main observation at this point is that introducing a new token means
that there is no way to use this in code that has to be backwards
compatible with Python 3.9 and before (assuming you could get it into
3.10). This is different for PEP 604's `|` operator, which can be used in
Python 3.7+ as long as the `from __future__ import annotations` magic
import is used to avoid runtime errors on things like `int | str`. The `|`
operator could also be used in typeshed, since it is valid Python 3.7
syntax. (While I don't know of any type checkers that currently support it
yet, supporting it would not require changes to the Python *parser* -- at
least typed_ast can handle it without changes.)
However, this shouldn't be a big strike against the proposal. In a few
short years Python 3.10 will be the oldest version supported and all will
be well.
Another concern I have is that we already have two ways to spell
"optional": `Optional[T]` and `T | None`.
Finally, IMO the argument against `Optional[T]` is stronger than the
argument against `T | None`. (But your point that 7% of annotations use
Optional is well taken.)
--Guido
On Thu, Sep 3, 2020 at 12:04 PM None via Typing-sig
Hi there,
Recently I have been working on an implementation for PEP 604 ( https://www.python.org/dev/peps/pep-0604/). While working on this, I started reviewing and exploring what new Optional syntax would look like in the Python language.
I've written a rough draft of a PEP and wanted to present it to this email list before submitting a PR. I know this is a topic that has been discussed in many settings (Github issues, in person typing meetups, etc. )previously, and wanted to solicit feedback here first. Let me know if submitting a PR would be a better way to gauge sentiment and feedback on this proposal.
Draft Proposal (branch compare): https://github.com/python/peps/compare/master...MaggieMoss:optional-syntax-p... Gist: https://gist.github.com/MaggieMoss/c848cb3a581979f445d075c15629c950
Thanks again, Maggie _______________________________________________ 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: guido@python.org
-- --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...
Nice. This ? makes sense to me, especially given the similar use in many
other languages.
Though I wonder how to represent `Union[bytes, str]?` using the | syntax.
`(bytes | str)?` or `bytes? | str?`. That should be covered.
I believe Thomas Wouters (cc'd) has been mulling over ? as a token for a
non conflicting non-typing purpose. Maybe this is the decade of the ?.
I'm not worried about being unable to use a new feature on older versions
of the language. That is normal, there is always a long time frame before a
syntax feature can see wide adoption. (ex: yield, with, set literals,
1_000, async, ...)
-gps
On Thu, Sep 3, 2020, 3:19 PM Guido van Rossum
Wow, you've been busy! (I know I still owe you a review on the PEP 604 implementation. It's on my TODO list. :-)
My main observation at this point is that introducing a new token means that there is no way to use this in code that has to be backwards compatible with Python 3.9 and before (assuming you could get it into 3.10). This is different for PEP 604's `|` operator, which can be used in Python 3.7+ as long as the `from __future__ import annotations` magic import is used to avoid runtime errors on things like `int | str`. The `|` operator could also be used in typeshed, since it is valid Python 3.7 syntax. (While I don't know of any type checkers that currently support it yet, supporting it would not require changes to the Python *parser* -- at least typed_ast can handle it without changes.)
However, this shouldn't be a big strike against the proposal. In a few short years Python 3.10 will be the oldest version supported and all will be well.
Another concern I have is that we already have two ways to spell "optional": `Optional[T]` and `T | None`.
Finally, IMO the argument against `Optional[T]` is stronger than the argument against `T | None`. (But your point that 7% of annotations use Optional is well taken.)
--Guido
On Thu, Sep 3, 2020 at 12:04 PM None via Typing-sig
wrote: Hi there,
Recently I have been working on an implementation for PEP 604 ( https://www.python.org/dev/peps/pep-0604/). While working on this, I started reviewing and exploring what new Optional syntax would look like in the Python language.
I've written a rough draft of a PEP and wanted to present it to this email list before submitting a PR. I know this is a topic that has been discussed in many settings (Github issues, in person typing meetups, etc. )previously, and wanted to solicit feedback here first. Let me know if submitting a PR would be a better way to gauge sentiment and feedback on this proposal.
Draft Proposal (branch compare): https://github.com/python/peps/compare/master...MaggieMoss:optional-syntax-p... Gist: https://gist.github.com/MaggieMoss/c848cb3a581979f445d075c15629c950
Thanks again, Maggie _______________________________________________ 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: guido@python.org
-- --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: greg@krypto.org
Though I wonder how to represent `Union[bytes, str]?` using the | syntax. `(bytes | str)?` or `bytes? | str?`
Good question! From the theoretical point of view, all your examples should
be equal.
Since Union always maintains its structure.
Currently, it works correctly:
```
from typing import Optional, Union
x: Optional[Union[int, str]]
y: Union[Optional[int], Optional[str]]
reveal_type(x) # Union[builtins.int, builtins.str, None]
reveal_type(y) # Union[builtins.int, None, builtins.str, None]
```
However, mypy can possibly flatten repeating `None` values, but that's
another topic.
пт, 4 сент. 2020 г. в 01:48, Gregory P. Smith
Nice. This ? makes sense to me, especially given the similar use in many other languages.
Though I wonder how to represent `Union[bytes, str]?` using the | syntax. `(bytes | str)?` or `bytes? | str?`. That should be covered.
I believe Thomas Wouters (cc'd) has been mulling over ? as a token for a non conflicting non-typing purpose. Maybe this is the decade of the ?.
I'm not worried about being unable to use a new feature on older versions of the language. That is normal, there is always a long time frame before a syntax feature can see wide adoption. (ex: yield, with, set literals, 1_000, async, ...)
-gps
On Thu, Sep 3, 2020, 3:19 PM Guido van Rossum
wrote: Wow, you've been busy! (I know I still owe you a review on the PEP 604 implementation. It's on my TODO list. :-)
My main observation at this point is that introducing a new token means that there is no way to use this in code that has to be backwards compatible with Python 3.9 and before (assuming you could get it into 3.10). This is different for PEP 604's `|` operator, which can be used in Python 3.7+ as long as the `from __future__ import annotations` magic import is used to avoid runtime errors on things like `int | str`. The `|` operator could also be used in typeshed, since it is valid Python 3.7 syntax. (While I don't know of any type checkers that currently support it yet, supporting it would not require changes to the Python *parser* -- at least typed_ast can handle it without changes.)
However, this shouldn't be a big strike against the proposal. In a few short years Python 3.10 will be the oldest version supported and all will be well.
Another concern I have is that we already have two ways to spell "optional": `Optional[T]` and `T | None`.
Finally, IMO the argument against `Optional[T]` is stronger than the argument against `T | None`. (But your point that 7% of annotations use Optional is well taken.)
--Guido
On Thu, Sep 3, 2020 at 12:04 PM None via Typing-sig < typing-sig@python.org> wrote:
Hi there,
Recently I have been working on an implementation for PEP 604 ( https://www.python.org/dev/peps/pep-0604/). While working on this, I started reviewing and exploring what new Optional syntax would look like in the Python language.
I've written a rough draft of a PEP and wanted to present it to this email list before submitting a PR. I know this is a topic that has been discussed in many settings (Github issues, in person typing meetups, etc. )previously, and wanted to solicit feedback here first. Let me know if submitting a PR would be a better way to gauge sentiment and feedback on this proposal.
Draft Proposal (branch compare): https://github.com/python/peps/compare/master...MaggieMoss:optional-syntax-p... Gist: https://gist.github.com/MaggieMoss/c848cb3a581979f445d075c15629c950
Thanks again, Maggie _______________________________________________ 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: guido@python.org
-- --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: greg@krypto.org
_______________________________________________ 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: n.a.sobolev@gmail.com
Thanks for the feedback.
One additional question here: Would anyone like to sponsor this PEP?
Thanks,
Maggie
________________________________
From: Guido van Rossum
On Fri, Sep 4, 2020 at 12:14 AM Никита Соболев
Though I wonder how to represent `Union[bytes, str]?` using the | syntax. `(bytes | str)?` or `bytes? | str?`
Good question! From the theoretical point of view, all your examples should be equal. Since Union always maintains its structure.
Currently, it works correctly:
``` from typing import Optional, Union
x: Optional[Union[int, str]] y: Union[Optional[int], Optional[str]]
reveal_type(x) # Union[builtins.int, builtins.str, None] reveal_type(y) # Union[builtins.int, None, builtins.str, None] ```
However, mypy can possibly flatten repeating `None` values, but that's another topic.
I know they are equivalent and can both be used. My question (which you didn't answer) is which variant should we recommend, and why? I honestly find both `(bytes | str)?` and `bytes? | str?` unpleasant to look at, and the fact that it's not clear which is better makes it even worse. We could even recommend `bytes | str?` but that's even weirder. In contrast, if we don't introduce `?`, then `bytes | str | None` is clear and looks more readable to me; and there's no other variant (you could argue about `None | bytes | str` but that's of the same order as whether to write `bytes | str` or `str | bytes`). All of which IMO is a ding against adding `?`. -- --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...
The requirement of having a PEP sponsor is to make sure that poorly
thought-out proposals are stopped with minimal waste of resources. Your
proposal, even though I am not particularly in favor of it, deserves to be
a discussion to have. (For example, it seems that TypeScript is surviving
even though it also has this problem of how best to write
`Optional[Union[...]]`.)
So if you can't find someone else to sponsor it, I will, even though when
it comes down to accepting it I would probably recommend that the SC reject
it. Even that would be useful, since then we can point to the rejected PEP
when the idea is brought up again. :-)
Finally -- wouldn't we need to have a new dunder method/protocol so the
operator can be overloaded for other functionality?
On Wed, Sep 9, 2020 at 3:12 PM Maggie Moss
Thanks for the feedback.
One additional question here: Would anyone like to sponsor this PEP?
Thanks, Maggie ------------------------------ *From:* Guido van Rossum
*Sent:* Thursday, September 3, 2020 3:18 PM *To:* Maggie Moss *Cc:* typing-sig@python.org *Subject:* Re: [Typing-sig] Update: Work on Optional Syntax PEP Wow, you've been busy! (I know I still owe you a review on the PEP 604 implementation. It's on my TODO list. :-)
My main observation at this point is that introducing a new token means that there is no way to use this in code that has to be backwards compatible with Python 3.9 and before (assuming you could get it into 3.10). This is different for PEP 604's `|` operator, which can be used in Python 3.7+ as long as the `from __future__ import annotations` magic import is used to avoid runtime errors on things like `int | str`. The `|` operator could also be used in typeshed, since it is valid Python 3.7 syntax. (While I don't know of any type checkers that currently support it yet, supporting it would not require changes to the Python *parser* -- at least typed_ast can handle it without changes.)
However, this shouldn't be a big strike against the proposal. In a few short years Python 3.10 will be the oldest version supported and all will be well.
Another concern I have is that we already have two ways to spell "optional": `Optional[T]` and `T | None`.
Finally, IMO the argument against `Optional[T]` is stronger than the argument against `T | None`. (But your point that 7% of annotations use Optional is well taken.)
--Guido
On Thu, Sep 3, 2020 at 12:04 PM None via Typing-sig
wrote: Hi there,
Recently I have been working on an implementation for PEP 604 ( https://www.python.org/dev/peps/pep-0604/ https://urldefense.proofpoint.com/v2/url?u=https-3A__www.python.org_dev_peps_pep-2D0604_&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=f28uZNOWonDFk7FJQDoV1HxAt9325GELs0nSw_fZ-QQ&m=0jLG3fTmrb4AQ6ZhABOSg26ax9ZdSRYxgUFXFZj2kyg&s=J96mesCJIlD6NfDAAsXL0dFJXR920_vBYasEq8Zgn6A&e=). While working on this, I started reviewing and exploring what new Optional syntax would look like in the Python language.
I've written a rough draft of a PEP and wanted to present it to this email list before submitting a PR. I know this is a topic that has been discussed in many settings (Github issues, in person typing meetups, etc. )previously, and wanted to solicit feedback here first. Let me know if submitting a PR would be a better way to gauge sentiment and feedback on this proposal.
Draft Proposal (branch compare): https://github.com/python/peps/compare/master...MaggieMoss:optional-syntax-p... Gist: https://gist.github.com/MaggieMoss/c848cb3a581979f445d075c15629c950
Thanks again, Maggie _______________________________________________ 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/ https://urldefense.proofpoint.com/v2/url?u=https-3A__mail.python.org_mailman3_lists_typing-2Dsig.python.org_&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=f28uZNOWonDFk7FJQDoV1HxAt9325GELs0nSw_fZ-QQ&m=0jLG3fTmrb4AQ6ZhABOSg26ax9ZdSRYxgUFXFZj2kyg&s=ZeTEN7ql-2_nV4tE3l7PRyEUj6YjwgYR2QlFR3F9QRs&e= Member address: guido@python.org
-- --Guido van Rossum (python.org/~guido https://urldefense.proofpoint.com/v2/url?u=http-3A__python.org_-7Eguido&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=f28uZNOWonDFk7FJQDoV1HxAt9325GELs0nSw_fZ-QQ&m=0jLG3fTmrb4AQ6ZhABOSg26ax9ZdSRYxgUFXFZj2kyg&s=WzHjojUuk8ytY-7ARrq2LELrpwxQNeOsZCaQ867H_Sk&e= ) *Pronouns: he/him **(why is my pronoun here?)* https://urldefense.proofpoint.com/v2/url?u=http-3A__feministing.com_2015_02_03_how-2Dusing-2Dthey-2Das-2Da-2Dsingular-2Dpronoun-2Dcan-2Dchange-2Dthe-2Dworld_&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=f28uZNOWonDFk7FJQDoV1HxAt9325GELs0nSw_fZ-QQ&m=0jLG3fTmrb4AQ6ZhABOSg26ax9ZdSRYxgUFXFZj2kyg&s=1RqmKCAxL8BNbxJclFdhkTeLb0_yNHHeJBmQLFM3-oQ&e=
-- --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...
My question (which you didn't answer) is which variant should we recommend, and why? I honestly find both `(bytes | str)?` and `bytes? | str?` unpleasant to look at, and the fact that it's not clear which is better makes it even worse. We could even recommend `bytes | str?` but that's even weirder.
Yes, I agree that all `|` variants with `?` do not look too pleasant.
And that multiple possibilities to write the same things make it even
worse.
Here I want to show some examples from other languages that already have
this feature.
TypeScript. It has both `null` and `undefined`. So, there are two syntax
constructs to represent it: `| null` and `?` respectively.
There's a setting to change this a bit, but let's omit it for now. We are
going to use the `--strict` version.
function worksWithOptional(param?: number) {}
worksWithOptional(1)
worksWithOptional(undefined)
function worksWithNullable(param: number | null) {}
worksWithNullable(1)
worksWithNullable(null)
function worksWithUnion(param: number | string) {}
function worksWithOptionalUnion(param?: number | string) {}
function worksWithNullableUnion(param: number | string | null) {}
It is clear why TypeScript has both `?` and `| null`, because in JS there
are two "empty" states.
But, it is also important to highlight that TypeScript does not have this
`str? | bytes` vs `(str | bytes)?` problem.
It either has a single `?` near the argument / property definition, or
union with explicit `null`
Flow is a bit different. It allows both `null` and `undefined` to be under
`?` when placed in type definition.
And also has `?` near arguments / props to mark them to work with
`undefined`, but not `null`.
See
https://stackoverflow.com/questions/50112490/what-is-the-difference-between-...
/* @flow */
function foo(x: ?number | string) {}
foo(undefined)
foo(null)
foo(1)
function bar(x: ?(number | string)) {}
bar(undefined)
bar(null)
bar(1)
function baz(x: number | ?string) {}
baz(undefined)
baz(null)
baz(1)
function withOptional(x?: number) {}
withOptional(1)
withOptional(undefined)
It looks way less readable compared to TS.
Scala (which is mentioned in the original PEP) (dotty) has only a single
way of doing it: `Int|String|Null`
https://dotty.epfl.ch/docs/reference/other-new-features/explicit-nulls.html
Currently it is in development and things may change. It has no special
syntax for `Null`. Scala usually uses the `Maybe` monad to handle empty
states, so there's no need for a special syntax.
Other languages either don't have `?` syntax (like Scala and Julia), or
have different `Null` concepts (like Rust and Haskell), or have different
Union concepts (like Swift, Kotlin and Rust), or go really wild in terms of
syntax like `T.nilable(T.any(Number | String))` in Ruby or `float() |
none()` in Elixir.
So, there is nowhere to copy any alternative solutions from. At least in
the mainstream languages.
My personal opinion:
1. This looks great, way better than now with `Optional`: `def some(arg:
str? = None): ...` compare it with
```
from typing import Optional
def some(arg: Optional[str] = None): ...
```
2. This looks a bit less great: `def other(arg: str | None = None): ...`
But still pretty pleasant
3. The union solution (2) does scale. It can easily become `str | bytes |
None`
4. The `?` (1) solution does not scale well, as I have shown above, `str?`
has trouble becoming `str? | bytes` or `(str | bytes)?`
(I even don't mention other possible types operators like `&` for
intersections that can be added later)
чт, 10 сент. 2020 г. в 03:08, Guido van Rossum
The requirement of having a PEP sponsor is to make sure that poorly thought-out proposals are stopped with minimal waste of resources. Your proposal, even though I am not particularly in favor of it, deserves to be a discussion to have. (For example, it seems that TypeScript is surviving even though it also has this problem of how best to write `Optional[Union[...]]`.)
So if you can't find someone else to sponsor it, I will, even though when it comes down to accepting it I would probably recommend that the SC reject it. Even that would be useful, since then we can point to the rejected PEP when the idea is brought up again. :-)
Finally -- wouldn't we need to have a new dunder method/protocol so the operator can be overloaded for other functionality?
On Wed, Sep 9, 2020 at 3:12 PM Maggie Moss
wrote: Thanks for the feedback.
One additional question here: Would anyone like to sponsor this PEP?
Thanks, Maggie ------------------------------ *From:* Guido van Rossum
*Sent:* Thursday, September 3, 2020 3:18 PM *To:* Maggie Moss *Cc:* typing-sig@python.org *Subject:* Re: [Typing-sig] Update: Work on Optional Syntax PEP Wow, you've been busy! (I know I still owe you a review on the PEP 604 implementation. It's on my TODO list. :-)
My main observation at this point is that introducing a new token means that there is no way to use this in code that has to be backwards compatible with Python 3.9 and before (assuming you could get it into 3.10). This is different for PEP 604's `|` operator, which can be used in Python 3.7+ as long as the `from __future__ import annotations` magic import is used to avoid runtime errors on things like `int | str`. The `|` operator could also be used in typeshed, since it is valid Python 3.7 syntax. (While I don't know of any type checkers that currently support it yet, supporting it would not require changes to the Python *parser* -- at least typed_ast can handle it without changes.)
However, this shouldn't be a big strike against the proposal. In a few short years Python 3.10 will be the oldest version supported and all will be well.
Another concern I have is that we already have two ways to spell "optional": `Optional[T]` and `T | None`.
Finally, IMO the argument against `Optional[T]` is stronger than the argument against `T | None`. (But your point that 7% of annotations use Optional is well taken.)
--Guido
On Thu, Sep 3, 2020 at 12:04 PM None via Typing-sig < typing-sig@python.org> wrote:
Hi there,
Recently I have been working on an implementation for PEP 604 ( https://www.python.org/dev/peps/pep-0604/ https://urldefense.proofpoint.com/v2/url?u=https-3A__www.python.org_dev_peps_pep-2D0604_&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=f28uZNOWonDFk7FJQDoV1HxAt9325GELs0nSw_fZ-QQ&m=0jLG3fTmrb4AQ6ZhABOSg26ax9ZdSRYxgUFXFZj2kyg&s=J96mesCJIlD6NfDAAsXL0dFJXR920_vBYasEq8Zgn6A&e=). While working on this, I started reviewing and exploring what new Optional syntax would look like in the Python language.
I've written a rough draft of a PEP and wanted to present it to this email list before submitting a PR. I know this is a topic that has been discussed in many settings (Github issues, in person typing meetups, etc. )previously, and wanted to solicit feedback here first. Let me know if submitting a PR would be a better way to gauge sentiment and feedback on this proposal.
Draft Proposal (branch compare): https://github.com/python/peps/compare/master...MaggieMoss:optional-syntax-p... Gist: https://gist.github.com/MaggieMoss/c848cb3a581979f445d075c15629c950
Thanks again, Maggie _______________________________________________ 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/ https://urldefense.proofpoint.com/v2/url?u=https-3A__mail.python.org_mailman3_lists_typing-2Dsig.python.org_&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=f28uZNOWonDFk7FJQDoV1HxAt9325GELs0nSw_fZ-QQ&m=0jLG3fTmrb4AQ6ZhABOSg26ax9ZdSRYxgUFXFZj2kyg&s=ZeTEN7ql-2_nV4tE3l7PRyEUj6YjwgYR2QlFR3F9QRs&e= Member address: guido@python.org
-- --Guido van Rossum (python.org/~guido https://urldefense.proofpoint.com/v2/url?u=http-3A__python.org_-7Eguido&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=f28uZNOWonDFk7FJQDoV1HxAt9325GELs0nSw_fZ-QQ&m=0jLG3fTmrb4AQ6ZhABOSg26ax9ZdSRYxgUFXFZj2kyg&s=WzHjojUuk8ytY-7ARrq2LELrpwxQNeOsZCaQ867H_Sk&e= ) *Pronouns: he/him **(why is my pronoun here?)* https://urldefense.proofpoint.com/v2/url?u=http-3A__feministing.com_2015_02_03_how-2Dusing-2Dthey-2Das-2Da-2Dsingular-2Dpronoun-2Dcan-2Dchange-2Dthe-2Dworld_&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=f28uZNOWonDFk7FJQDoV1HxAt9325GELs0nSw_fZ-QQ&m=0jLG3fTmrb4AQ6ZhABOSg26ax9ZdSRYxgUFXFZj2kyg&s=1RqmKCAxL8BNbxJclFdhkTeLb0_yNHHeJBmQLFM3-oQ&e=
-- --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: n.a.sobolev@gmail.com
Note that in Typescript, the `?` suffix is only accepted in specific
constructs and has different semantics than just building an optional type.
This can be used to denote optional fields in an interface (somewhat akin
to TypedDict) see
https://www.typescriptlang.org/docs/handbook/interfaces.html#optional-proper...
and denote an optional parameter
https://www.typescriptlang.org/docs/handbook/functions.html#optional-and-def...,
i.e., the parameter does not need to be explicitly passed to the function.
For example, in an interface bar?: number; is not the same as bar: number
| undefined; (see playground
https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgPIAczAPYjgGwDFg...
):
interface OptionalFields {
foo: number;
bar?: number;
}
const test1: OptionalFields = {
foo: 1
}
interface RequiredButPossibleUndefinedFields {
foo: number;
bar: number | undefined;
}
// This is invalid. Compare it to test1
const test4: RequiredButPossibleUndefinedFields = {
foo: 1
}
In other type declarations, like generics, one needs to use the full
spelling, for example Promise
My question (which you didn't answer) is which variant should we recommend, and why? I honestly find both `(bytes | str)?` and `bytes? | str?` unpleasant to look at, and the fact that it's not clear which is better makes it even worse. We could even recommend `bytes | str?` but that's even weirder.
Yes, I agree that all `|` variants with `?` do not look too pleasant. And that multiple possibilities to write the same things make it even worse.
Here I want to show some examples from other languages that already have this feature.
TypeScript. It has both `null` and `undefined`. So, there are two syntax constructs to represent it: `| null` and `?` respectively. There's a setting to change this a bit, but let's omit it for now. We are going to use the `--strict` version.
function worksWithOptional(param?: number) {}
worksWithOptional(1) worksWithOptional(undefined)
function worksWithNullable(param: number | null) {}
worksWithNullable(1) worksWithNullable(null)
function worksWithUnion(param: number | string) {}
function worksWithOptionalUnion(param?: number | string) {}
function worksWithNullableUnion(param: number | string | null) {}
It is clear why TypeScript has both `?` and `| null`, because in JS there are two "empty" states. But, it is also important to highlight that TypeScript does not have this `str? | bytes` vs `(str | bytes)?` problem. It either has a single `?` near the argument / property definition, or union with explicit `null`
Flow is a bit different. It allows both `null` and `undefined` to be under `?` when placed in type definition. And also has `?` near arguments / props to mark them to work with `undefined`, but not `null`. See https://stackoverflow.com/questions/50112490/what-is-the-difference-between-... /* @flow */
function foo(x: ?number | string) {}
foo(undefined) foo(null) foo(1)
function bar(x: ?(number | string)) {}
bar(undefined) bar(null) bar(1)
function baz(x: number | ?string) {}
baz(undefined) baz(null) baz(1)
function withOptional(x?: number) {}
withOptional(1) withOptional(undefined)
It looks way less readable compared to TS.
Scala (which is mentioned in the original PEP) (dotty) has only a single way of doing it: `Int|String|Null` https://dotty.epfl.ch/docs/reference/other-new-features/explicit-nulls.html Currently it is in development and things may change. It has no special syntax for `Null`. Scala usually uses the `Maybe` monad to handle empty states, so there's no need for a special syntax.
Other languages either don't have `?` syntax (like Scala and Julia), or have different `Null` concepts (like Rust and Haskell), or have different Union concepts (like Swift, Kotlin and Rust), or go really wild in terms of syntax like `T.nilable(T.any(Number | String))` in Ruby or `float() | none()` in Elixir.
So, there is nowhere to copy any alternative solutions from. At least in the mainstream languages.
My personal opinion: 1. This looks great, way better than now with `Optional`: `def some(arg: str? = None): ...` compare it with
``` from typing import Optional
def some(arg: Optional[str] = None): ... ```
2. This looks a bit less great: `def other(arg: str | None = None): ...` But still pretty pleasant 3. The union solution (2) does scale. It can easily become `str | bytes | None` 4. The `?` (1) solution does not scale well, as I have shown above, `str?` has trouble becoming `str? | bytes` or `(str | bytes)?`
(I even don't mention other possible types operators like `&` for intersections that can be added later)
чт, 10 сент. 2020 г. в 03:08, Guido van Rossum
: The requirement of having a PEP sponsor is to make sure that poorly thought-out proposals are stopped with minimal waste of resources. Your proposal, even though I am not particularly in favor of it, deserves to be a discussion to have. (For example, it seems that TypeScript is surviving even though it also has this problem of how best to write `Optional[Union[...]]`.)
So if you can't find someone else to sponsor it, I will, even though when it comes down to accepting it I would probably recommend that the SC reject it. Even that would be useful, since then we can point to the rejected PEP when the idea is brought up again. :-)
Finally -- wouldn't we need to have a new dunder method/protocol so the operator can be overloaded for other functionality?
On Wed, Sep 9, 2020 at 3:12 PM Maggie Moss
wrote: Thanks for the feedback.
One additional question here: Would anyone like to sponsor this PEP?
Thanks, Maggie ------------------------------ *From:* Guido van Rossum
*Sent:* Thursday, September 3, 2020 3:18 PM *To:* Maggie Moss *Cc:* typing-sig@python.org *Subject:* Re: [Typing-sig] Update: Work on Optional Syntax PEP Wow, you've been busy! (I know I still owe you a review on the PEP 604 implementation. It's on my TODO list. :-)
My main observation at this point is that introducing a new token means that there is no way to use this in code that has to be backwards compatible with Python 3.9 and before (assuming you could get it into 3.10). This is different for PEP 604's `|` operator, which can be used in Python 3.7+ as long as the `from __future__ import annotations` magic import is used to avoid runtime errors on things like `int | str`. The `|` operator could also be used in typeshed, since it is valid Python 3.7 syntax. (While I don't know of any type checkers that currently support it yet, supporting it would not require changes to the Python *parser* -- at least typed_ast can handle it without changes.)
However, this shouldn't be a big strike against the proposal. In a few short years Python 3.10 will be the oldest version supported and all will be well.
Another concern I have is that we already have two ways to spell "optional": `Optional[T]` and `T | None`.
Finally, IMO the argument against `Optional[T]` is stronger than the argument against `T | None`. (But your point that 7% of annotations use Optional is well taken.)
--Guido
On Thu, Sep 3, 2020 at 12:04 PM None via Typing-sig < typing-sig@python.org> wrote:
Hi there,
Recently I have been working on an implementation for PEP 604 ( https://www.python.org/dev/peps/pep-0604/ https://urldefense.proofpoint.com/v2/url?u=https-3A__www.python.org_dev_peps_pep-2D0604_&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=f28uZNOWonDFk7FJQDoV1HxAt9325GELs0nSw_fZ-QQ&m=0jLG3fTmrb4AQ6ZhABOSg26ax9ZdSRYxgUFXFZj2kyg&s=J96mesCJIlD6NfDAAsXL0dFJXR920_vBYasEq8Zgn6A&e=). While working on this, I started reviewing and exploring what new Optional syntax would look like in the Python language.
I've written a rough draft of a PEP and wanted to present it to this email list before submitting a PR. I know this is a topic that has been discussed in many settings (Github issues, in person typing meetups, etc. )previously, and wanted to solicit feedback here first. Let me know if submitting a PR would be a better way to gauge sentiment and feedback on this proposal.
Draft Proposal (branch compare): https://github.com/python/peps/compare/master...MaggieMoss:optional-syntax-p... Gist: https://gist.github.com/MaggieMoss/c848cb3a581979f445d075c15629c950
Thanks again, Maggie _______________________________________________ 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/ https://urldefense.proofpoint.com/v2/url?u=https-3A__mail.python.org_mailman3_lists_typing-2Dsig.python.org_&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=f28uZNOWonDFk7FJQDoV1HxAt9325GELs0nSw_fZ-QQ&m=0jLG3fTmrb4AQ6ZhABOSg26ax9ZdSRYxgUFXFZj2kyg&s=ZeTEN7ql-2_nV4tE3l7PRyEUj6YjwgYR2QlFR3F9QRs&e= Member address: guido@python.org
-- --Guido van Rossum (python.org/~guido https://urldefense.proofpoint.com/v2/url?u=http-3A__python.org_-7Eguido&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=f28uZNOWonDFk7FJQDoV1HxAt9325GELs0nSw_fZ-QQ&m=0jLG3fTmrb4AQ6ZhABOSg26ax9ZdSRYxgUFXFZj2kyg&s=WzHjojUuk8ytY-7ARrq2LELrpwxQNeOsZCaQ867H_Sk&e= ) *Pronouns: he/him **(why is my pronoun here?)* https://urldefense.proofpoint.com/v2/url?u=http-3A__feministing.com_2015_02_03_how-2Dusing-2Dthey-2Das-2Da-2Dsingular-2Dpronoun-2Dcan-2Dchange-2Dthe-2Dworld_&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=f28uZNOWonDFk7FJQDoV1HxAt9325GELs0nSw_fZ-QQ&m=0jLG3fTmrb4AQ6ZhABOSg26ax9ZdSRYxgUFXFZj2kyg&s=1RqmKCAxL8BNbxJclFdhkTeLb0_yNHHeJBmQLFM3-oQ&e=
-- --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: n.a.sobolev@gmail.com
_______________________________________________ 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: skreft@gmail.com
-- Sebastian Kreft
Thanks so much for the responses to the initial PEP draft. - Shorthand Union + Optional Convention I wanted to address this question:
My question [...] is which variant should we recommend, and why?
Reading through the examples provided, Flow provides syntax most similar to the optional syntax proposed in the PEP. ``` // Flow examples. function foo(x: ?number | string) {} function bar(x: ?(number | string)) {} function baz(x: number | ?string) {} ```
It looks way less readable compared to TS.
In my opinion, this looks less readable because of the placement of the ? operator. For the Python syntax, I would suggest that the convention be to always add the ? at the end of the annotation. ``` # examples def foo(x: int | str?): ... def bar(x: list[int | str?]): ... ``` Of the available options, I find this to be the easiest to digest at a glance, and the most concise. - Dunder Method
Finally -- wouldn't we need to have a new dunder method/protocol so the operator can be overloaded for other functionality?
Yes, thanks so much for this, we would need a new dunder method. I will update the PEP draft and the linked reference implementation. - Sponsorship
So if you can't find someone else to sponsor it, I will, even though when it comes down to accepting it I would probably recommend that the SC reject it. Even that would be useful, since then we can point to the rejected PEP when the idea is brought up again. :-)
I appreciate the honesty. Thanks for offering! :) As next steps, I'll update the PEP draft with these suggestions. Thanks again, Maggie
participants (6)
-
Gregory P. Smith
-
Guido van Rossum
-
Maggie Moss
-
maggiemoss@fb.com
-
Sebastian Kreft
-
Никита Соболев