[Rhodri James]

> We could argue about how intuitive or not these operators are, but they
>>> are used in other languages, so they clearly aren't completely
>>> unintuitive.
>>>
>>
>> Other languages are other languages. Other languages use the "<condition>
>> ?
>> <expr_a> : <expr_b>" form of the the ternary operator. That doesn't mean
>> we
>> should adopt that into Python.
>>
>
> But it does and did mean that we should consider it when coming up with
> Python's version of the ternary operator.  *It isn't unintuitive* and
> neither is ??  None-aware operators may be bad for other reasons, but that
> argument doesn't wash.


No. The fact that other languages use it doesn't mean that "it isn't
unintuitive". The fact that other languages use it doesn't mean that it
doesn't harm readability. The fact that other languages use it has pretty
much no bearing on any of that. What it actually means is: other languages
are trying it out so we have the luxury of seeing if they regret it in the
future or if it becomes a popular and well loved feature before integrating
it into Python.

I believe it's counter-intuitive because '?' always comes at the end of an
english sentence, so it reads like other clause-ending operators like the
")" on a function call or the "]" at the end of a index operation, then the
"." reads like a follow-on.

And no; you can't say the same thing about "." always coming at the end of
a sentence because:

a) that's not true (e.g. i.e, e.g., etc.)

b) "." attribute access has many decades of precedence

c) a "." is less visually obtrusive than a "?".

[Rhodri James]

>  Pardon?  It composes exactly like any other in-place operator.


Yes. I'll concede. I was wrong about that.

[Rhodri James]

> yes, you do need to explain how merely being high precedence helps here.
> Let's start small; please explain programmatically what


>   name?



does as an expression.  Once we have that down, we can move on to



  person.(name?)


Sure. First, I would suggest we define a new class
NoneException(BaseException), and derive new Exception multi-classes like:
class NoneAttributeError(AttributeError, NoneException).
Then I would make those the exceptions thrown by attribute errors on the
None object. That way you can conceptualize the '?' operator is to the
try-except statement as the ternary operator is to if-else statements
EXCEPT that the "except" part of the try-except block is implicitly filled
in with "except NoneException: return None" so in general:

<expression>?

Would parse to:

try:
    result = eval(expression)
except NoneException:
    result = None

Similar to how:

<expression_1> if <condition_expression> else <expression_2>

Parses to:

if eval(condition_expression):
    result = eval(expression_1)
else:
    result = eval(expression_2)

More specifically:

name?

Wouldn't do much:

try:
    result = name
except NoneException:
    result = None

And:

person.(name?)

would throw a SyntaxError because person.( is not valid syntax regardless
of my proposal.
Perhaps you meant something like:

(person.name).first?

In that case; person.name would evaluate to some result or throw an
un-guarded AttributeError, in the former case the <expression> to the left
of the '?' is an attribute access on the result of (person.name). In the
latter case; an AttributeError is thrown.

That seems pretty straight forward. No?

On 29/07/18 16:12, Abe Dillon wrote:

>  > spam?.eggs.cheese.aardvark  # why would you ever do this?



> If you knew that if you really have something in "spam", your program
> guarantees it will have an "eggs" attribute with a "cheese" attribute, etc,
> you just don't know if "spam" is not None.  It's the same insider knowledge
> you would use if you wrote it out as




> spam.eggs.cheese.aardvark if spam is not None else None


That's not the equivalent as described in PEP 505. If "spam" is None,
"spam?.eggs" evaluates to None without throwing an AttributeError, but the
rest of the expression will throw an AttributeError from trying to access
"None.cheese".

On Mon, Jul 30, 2018 at 9:10 AM, Rhodri James <rho...@kynesim.co.uk> wrote:

> On 29/07/18 16:12, Abe Dillon wrote:
>
>> spam?.eggs.cheese.aardvark  # why would you ever do this?
>>
>
> If you knew that if you really have something in "spam", your program
> guarantees it will have an "eggs" attribute with a "cheese" attribute, etc,
> you just don't know if "spam" is not None.  It's the same insider knowledge
> you would use if you wrote it out as
>
> spam.eggs.cheese.aardvark if spam is not None else None
>
> The same sort of knowledge of your program structure could lead to you to
> use "?." instead of "." in any place or places in the chain.  If your
> program gives you strong enough guarantees, it is the sort of thing you can
> use to reduce the code's workload.
>
> By way of example, I was working on some C code last night that was
> expanding an internal buffer, possibly from non-existence.  It did lot of
> taking the difference between various pointers to determine how big the new
> buffer needed to be, how much to copy from the old buffer, etc. It looked
> rather hairy until you realised that the code gave a strong guarantee that
> either all the pointers were meaningful or they were all NULL, so the
> pointer differences always made sense.  I rewrote that code so that it
> didn't take differences of NULL pointers since that was what the bug
> specified, but honestly it looks lumpier and less clear now.  A big comment
> explaining what was going on would probably be better.
>
> --
> Rhodri James *-* Kynesim Ltd
> _______________________________________________
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to