<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sat, Sep 19, 2015 at 7:06 AM, Steven D'Aprano <span dir="ltr"><<a href="mailto:steve@pearwood.info" target="_blank">steve@pearwood.info</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On Sat, Sep 19, 2015 at 03:17:07AM -0500, C Anthony Risinger wrote:<br>
<br>
> I really liked this whole thread, and I largely still do -- I?think -- but<br>
> I'm not sure I like how `?` suddenly prevents whole blocks of code from<br>
> being evaluated. Anything within the (...) or [...] is now skipped (IIUC)<br>
> just because a `?` was added, which seems like it could have side effects<br>
> on the surrounding state, especially since I expect people will use it for<br>
> squashing/silencing or as a convenient trick after the fact, possibly in<br>
> code they did not originally write.<br>
<br>
</span>I don't think this is any different from other short-circuiting<br>
operators, particularly `and` and the ternary `if` operator:<br>
<br>
result = obj and obj.method(expression)<br>
<br>
result = obj.method(expression) if obj else default<br>
<br>
In both cases, `expression` is not evaluated if obj is falsey. That's<br>
the whole point.</blockquote><div><br></div><div>Sure, but those all have white space and I can read what's happening. The `?` could appear anywhere without break. I don't like that, but, opinion.</div><div>Â </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> If the original example included a `?` like so:<br>
><br>
>Â Â Â response = json.dumps?({<br>
>Â Â Â Â Â 'created': created?.isoformat(),<br>
>Â Â Â Â Â 'updated': updated?.isoformat(),<br>
>Â Â Â Â Â ...<br>
>Â Â Â })<br>
><br>
> should "dumps" be None, the additional `?` (although though you can barely<br>
> see it) prevents *everything else* from executing.<br>
<br>
</span>We're still discussing the syntax and semantics of this, so I could be<br>
wrong, but my understanding of this is that the *first* question mark<br>
prevents the expressions in the parens from being executed:<br>
<br>
json.dumps?( ... )<br>
<br>
evaluates as None if json.dumps is None, otherwise it evaluates the<br>
arguments and calls the dumps object. In other words, rather like this:<br>
<br>
_temp = json.dumps # temporary value<br>
if _temp is None:<br>
  response = None<br>
else:<br>
  response = _temp({<br>
    'created': None if created is None else created.isoformat(),<br>
    'updated': None if updated is None else updated.isoformat(),<br>
    ...<br>
    })<br>
del _temp<br>
<br>
<br>
except the _temp name isn't actually used. The whole point is to avoid<br>
evaluating an expression (attribute looking, index/key lookup, function<br>
call) which will fail if the object is None, and if you're not going to<br>
call the function, why evaluate the arguments to the function?<br></blockquote><div>Â </div><div>Yes that is how I understand it as well. I'm suggesting it's hard to see. I understand the concept as "None cancellation", because if the left is None, the right is cancelled. This lead me here:</div><div><br></div><div>* This is great, want to use all the time!</div><div>* First-level language support, shouldn't I use? Does feels useful/natural</div><div>* How can I make my APIs cancellation-friendly?</div><div>* I can write None-centric APIs, that often collapse to None</div><div>* Now maybe user code does stuff like `patient.visits?.september?.records` to get all records in September (if any, else None)</div><div>* Since both `?` points would *prefer* None, if the result is None, I now have to jump around looking for who done it</div><div>* If I don't have debugger ATM, I'm breaking it up a lot for good 'ol print(...), only way</div><div>* I don't think I like this any more :(</div><div><br></div><div>I especially don't like the idea of seeing it multiple times quickly, and the potential impact to debugging. The truth is I want to like this but I feel like it opens a can of worms (as seen by all the wild operators this proposal "naturally" suggests).</div><div>Â </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">> Usually when I want to use this pattern, I find I just need to write things<br>
> out more. The concept itself vaguely reminds me of PHP's use of `@` for<br>
> squashing errors.<br>
<br>
</span>I had to look up PHP's @ and I must say I'm rather horrified. According<br>
to the docs, all it does is suppress the error reporting, it does<br>
nothing to prevent or recover from errors. There's not really an<br>
equivalent in Python, but I suppose this is the closest:<br>
<br>
# similar to PHP's $result = @(expression);<br>
try:<br>
  result = expression<br>
except:<br>
  result = None<br>
<br>
<br>
This is nothing like this proposal. It doesn't suppress arbitrary<br>
errors. It's more like a conditional:<br>
<br>
# result = obj?(expression)<br>
if obj is None:<br>
  result = None<br>
else:<br>
  result = obj(expression)<br>
<br>
<br>
If `expression` raises an exception, it will still be raised, but only<br>
if it is actually evaluated, just like anything else protected by an<br>
if...else or short-circuit operator.</blockquote><div><br></div><div>I did say vaguely :) but it is extremely hideous I agree. The part that made me think of this is the would be desire for things to become None (so, or example, wanting to avoid throwing typed/informative exceptions if possible) so they'd then be more useful with `?`.</div></div><div><br></div>-- <br><div class="gmail_signature"><br>C Anthony</div>
</div></div>