On Tue, Jul 24, 2018 at 12:05:14AM +0200, Giampaolo Rodola' wrote:
This:
v = a?.b
...*implicitly* checks if value is not None [and continues execution].
Do you agree that: obj.attribute x + 1 func(arg) explicitly looks up an attribute on obj, explicitly adds 1 to x, and explicitly calls func with a single argument? I don't think that we have to write COBOL-esque code to be explicit: GET ATTRIBUTE "attribute" FROM obj ADD 1 TO x CALL FUNCTION func WITH ARGUMENT arg I don't accept that the use of punctuation makes something implicit. But if you want to argue that anything with punctuation is "implicit", then okay, Python has lots of implicit punctuation. By definition, ?. checks for None before doing the attribute lookup. That is completely explicit, regardless of how it is spelled: obj?.attribute NULL-AWARE GET ATTRIBUTE "attribute" FROM obj null_aware_getattr(obj, "attribute") getattr_if_not_none(obj, "attribute") But what certainly *is* implicity is David Mertz' suggestion for a magical None-aware proxy: x.attribute The only way to tell whether that was an ordinary attribute lookup or a none-aware lookup would be to carefully inspect x and find out whether it was an instance of the None-aware proxy class or not.
This
v = a if a.b is not None: v = a.b
...*explicitly* checks if value is not None and continues execution.
If you are trying to match the behaviour of a?.b above, it is also completely buggy and doesn't do what is intended. # Equivalent of a?.b v = a if v is not None: v = v.b
If for some reason '?'[ is also going to swallow LookupError
What makes you think that ?[...] will swallow LookupError? Please don't argue against misfeatures that the PEP doesn't propose. Nothing in PEP 505 swallows any exceptions. Swallowing exceptions is explicitly rejected, and swallowing LookupError isn't part of the proposal. [...]
One may argue that silently returning None instead of raising AttributeError is also less explicit.
And again, you are arguing against a misfeature which PEP 505 does not propose. The ?. operator will not suppress AttributeErrors. # Wrong! No! This is not what the PEP proposes! obj = 1.234 assert obj?.hexx is None [...]
It isn't a first. Many existing operators use two adjacent symbols not interrupted by a space:
e.g. == <= >= != ** // << >> += -= *= etc.
You say 'a == b'. You can't say 'a ?. b' (not that it matters, it would be less intuitive anyway). You can't because '.?' is the only couple of contiguous symbols requiring "something" before and after with no spaces in between, and that's a first in the language.
Why do you think spaces aren't allowed? The PEP explicitly says that the new operators can be used wherever the regular operators can be used: "The maybe-dot and maybe-subscript operators are added as trailers for atoms, so that they may be used in all the same locations as the regular operators" and explicitly shows the grammar changes required: trailer: ('(' [arglist] ')' | '[' subscriptlist ']' | '?[' subscriptlist ']' | '.' NAME | '?.' NAME) That tells me that ?. will be legal anywhere . is legal, so if x . y is legal (and it is) so will x ?. y be legal. [...]
The difference is that 'a.b.c.d' will result in AttributeError as soon as something is None while 'a?.b?.c?.d' will return None instead.
Correct. Because sometimes you want an AttributeError, and sometimes you want None. You are criticising the operator for doing what it is designed and intended to do. You might as well criticise getattr(obj, 'spam', None) for returning None. If you want an AttributeError, then don't use ?. and use ordinary . instead.
Likewise the logical operators "or" and "and" are designed to short-circuit. If ?? and friends are a mistake because they short-circuit, why aren't "or" and "and" mistakes? I'm not asking this as a rhetorical question. If you think there is a reason why it is okay for or/and to short-circuit, but it is bad for ?? and friends to short-circuit, then please explain why they are different. I will be very happy to listen to your arguments.
The argument about this is that '?.' short-circuits execution *silently*.
Other short-circuit operators also short-circuit execution silently. That's what they are designed to do. # This isn't what actually happens. py> x = 0 py> result = x and 1/x __main__:1: UserWarning: Short-cut operation occurred, the right hand operand was not evaluated!!! Do not panic, this is the expected behaviour!!! py> print(result) 0
Instead of AttributeError you get None. You may chain ?. in order to lazily traverse a long tree,
Correct, that is what it is designed to do.
inadvertently assign None to a variable, continue code execution and fail later rather than sooner:
email = request?.context?.user?.email # None ... sendmail(subject, body, email)
Some (Antoine) rightly argued this may even have security implications (replace 'email' with 'password').
I'll have to remember that. Whenever there's any proposal for a feature I don't like, just claim it "may even have security implications". Who needs evidence when we have Fear, Uncertainty, Doubt? -- Steve