On Sat, Sep 19, 2015 at 12:02:42AM +0100, MRAB wrote:
To me, the choice _is_ obvious: "obj?[idx]". After all, that's more in keeping with "obj?.attr" and "func?()".
If you had "obj?[idx]", then shouldn't it also be "obj.?attr" and "func(?)"?
If I understand the idea, obj?.attr returns None if obj is None, otherwise returns obj.attr. The question mark (shrug operator?) applies to `obj` *before* the attribute lookup, so it should appear *before* the dot (since we read from left-to-right).
The heuristic for remembering the order is that the "shrug" (question mark) operator applies to obj, so it is attached to obj, before any subsequent operation.
For the sake of brevity, using @ as a placeholder for one of attribute access, item/key lookup, or function call, then we have:
as syntactic sugar for:
None if obj is None else obj@
Furthermore, we should be able to chain a sequence of such @s:
being equivalent to:
paperboy.receive(None if customer is None else customer.trousers.backpocket.wallet.extract(2.99) )
Let's just assume we have a good reason for chaining lookups that isn't an egregious violation of the Law of Demeter, and not get into a debate over OOP best practices, okay? :-)
Suppose that wallet itself may also be None. Then we can easily deal with that situation too:
which I think is a big win over either of these two alternatives:
# 1 paperboy.receive(None if customer is None else None if customer.trousers.backpocket.wallet is None else customer.trousers.backpocket.wallet.extract(2.99) )
# 2 if customer is not None: wallet = customer.trousers.backpocket.wallet if wallet is not None: paperboy.receive(wallet.extract(2.99))
It's a funny thing, I'm usually not a huge fan of symbols outside of maths operators, and I strongly dislike the C ? ternary operator, but this one feels really natural to me. I didn't have even the most momentary "if you want Perl, you know where to find it" thought.