Possibly relevant for tilde: https://www.thecut.com/article/why-the-internet-tilde-is-our-most-perfect-to... On Thu, Aug 29, 2019 at 5:09 PM Dominik Vilsmeier <dominik.vilsmeier@gmx.de> wrote:
Guido van Rossum wrote:
On Thu, Aug 29, 2019 at 4:04 PM Dominik Vilsmeier dominik.vilsmeier@gmx.de wrote:
I never really understood the importance of Optional. Often it can be left out altogether and in other cases I find Union[T, None] more expressive (explicit) than Optional[T] (+ the latter saves only 3 chars). I respectfully disagree. In our (huge) codebase we see way more occurrences of Optional than of Union. It's not that it saves a tremendous amount of typing -- it's a much more intuitive meaning. Every time I see Union[T, None] I have to read it carefully to see what it means. When I see Optional[T] my brain moves on immediately (in a sense it's only one bit of information).
You are probably right, it's all a matter of how used our brains are to seeing stuff. So if I started using it more frequently, after some time I would probably appreciate it over `Union[T, None]`.
Especially for people not familiar with typing, the meaning of Optional is not obvious at first sight. Union[T, None] on the other hand is pretty clear. Also in other cases, where the default (fallback) is different from None, you'd have to use Union anyway. For example a function that normally returns an object of type T but in some circumstances it cannot and then it returns the reason as a str, i.e. -> Union[T, str]; Optional won't help here. Scanning through the docs and PEP I can't find strongly motivating examples for Optional (over Union[T, None]). E.g. in the following: def lookup(self, name: str) -> Optional[Node]: nodes = self.get(name) if nodes: return nodes[-1] return None
I would rather write Union[Node, None] because that's much more explicit about what happens. Then introducing ~T in place of Optional[T] just further obfuscates the meaning of the code: def lookup(self, name: str) -> ~Node:
The ~ is easy to be missed (at least by human readers) and the meaning not obvious. Do you easily miss the - in an expression like -2?
I don't miss the `-` in the context because my brain is trained on recognizing such patterns. We encounter negative numbers everywhere, from (pre-)school on, so this pattern is easy to recognize. However `~Noun` is not something you've likely seen in the real world (or anywhere), so it's much harder to recognize. I cn wrt ths txt wtht vwls or eevn rdoerer teh lterets and you'll still be able to read it because your brain just fills in what it expects (i.e. what it is accustomed to). For that reason `~Node` is much harder to recognize than `-3637` because I wouldn't expect a `~` to appear in that place.
Surely the meaning of ? in a programming language also has to be learned. And not every language uses it to mean "optional" (IIRC there's a language where it means "boolean" -- maybe Scheme?)
For Union on the other hand it would be more helpful to have a shorter syntax, int | str seems pretty clear, but what prevents tuples (int, str) from being interpreted as unions by type checkers. This doesn't require any changes to the built-in types and it is aligned with the already existing syntax for checking multiple types with isinstance or issubclass: isinstance(x, (int, str)). Having used this a couple of times, whenever I see a tuple of types I immediately think of them as or options. First, if we were to introduce (int, str) it would make more sense for it to mean Tuple[int, str] (tuples are also a very common type). Second, comma is already very overloaded. Yes, it's unfortunately that (int, str) means "union" in isinstance() but it's not enough to sway me. Anyway, let's just paint the bikeshed some color. :-)
I don't think it's unfortunate, it's pretty neat syntax (and intuitive). Checking if `x` is an instance of `y` it makes sense to "list" (`tuple`) multiple options for `y`. It's a clever way of reusing the available syntax / functionality of the language. And I think this is what typing should do as well: build around the existing language and use whatever is available. Adding `__or__` to `type` for allowing things like `int | str` on the other hand bends the language toward typing and thus is a step in the opposite direction.
Then I don't think it's the comma that receives emphasis in the syntax `(int, str)`, it's rather the parens - and those, as a bonus, provide visual boundaries for the beginning and end of the union. Consider
def foo(x: str | int, y: list):
versus
def foo(x: (str, int), y: list):
The comma is a small character, visually the scene will be dominated by the matching parens - and whatever is inside is anyway a common sight as we are used to seeing tuples. Hence I think from readability perspective it's a plus to reuse existing, common syntax.
I agree that there is the ambiguity with `(int, str)` being interpreted as `Tuple[int, str]` and this is a valid argument. Since I've used the `isinstance(x, (y,z))` syntax quite often I wouldn't interpret `(int, str)` as a tuple but of course for other people the situation might be completely different. Hence that could really be a blocker. _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@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/ZONQON... Code of Conduct: http://python.org/psf/codeofconduct/
-- --Guido van Rossum (python.org/~guido) *Pronouns: he/him/his **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>