<div dir="ltr"><div class="gmail_default" style="font-family:monospace,monospace"><span style="font-family:arial,sans-serif">On Tue, Oct 10, 2017 at 5:46 PM, Yury Selivanov </span><span dir="ltr" style="font-family:arial,sans-serif"><<a href="mailto:yselivanov.ml@gmail.com" target="_blank">yselivanov.ml@gmail.com</a>></span><span style="font-family:arial,sans-serif"> wrote:</span><br></div><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail-HOEnZb"><div class="gmail-h5">On Tue, Oct 10, 2017 at 10:22 AM, Koos Zevenhoven <<a href="mailto:k7hoven@gmail.com">k7hoven@gmail.com</a>> wrote:<br>
> On Tue, Oct 10, 2017 at 5:01 PM, Nick Coghlan <<a href="mailto:ncoghlan@gmail.com">ncoghlan@gmail.com</a>> wrote:<br>
>><br>
>> On 10 October 2017 at 22:51, Koos Zevenhoven <<a href="mailto:k7hoven@gmail.com">k7hoven@gmail.com</a>> wrote:<br>
>>><br>
>>> I see no reason why these two should be equivalent.<br>
>><br>
>><br>
>> There is no "should" about it: it's a brute fact that the two forms *are*<br>
>> currently equivalent for lazy iterators (including generators), and both<br>
>> different from the form that uses eager evaluation of the values before the<br>
>> context change.<br>
>><br>
>> Where should enters into the picture is by way of PEP 550 saying that they<br>
>> should *remain* equivalent because we don't have an adequately compelling<br>
>> justification for changing the runtime semantics.<br>
>><br>
>> That is, given the following code:<br>
>><br>
>>     itr = make_iter()<br>
>>     with decimal.localcontext() as ctx:<br>
>>         ctc.prex = 30<br>
>>         for i in itr:<br>
>>           pass<br>
>><br>
>> Right now, today, in 3.6. the calculations in the iterator will use the<br>
>> modified decimal context, *not* the context that applied when the iterator<br>
>> was created. If you want to ensure that isn't the case, you have to force<br>
>> eager evaluation before the context change.<br>
>><br></div></div></blockquote><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">​It is not obvious to me if changing the semantics of this is breakage or a bug fix (as you put it below).​</div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail-HOEnZb"><div class="gmail-h5">
>> What PEP 550 is proposing is that, by default, *nothing changes*: the lazy<br>
>> iteration in the above will continue to use the updated decimal context by<br>
>> default.<br>
><br>
><br>
> That's just an arbitrary example. There are many things that *would* change<br>
> if decimal contexts simply switched from using thread-local storage to using<br>
> PEP 550. It's not at all obvious which of the changes would be most likely<br>
> to cause problems. If I were to choose, I would probably introduce a new<br>
> context manager which works with PEP 555 semantics, because that's the only<br>
> way to ensure full backwards compatibility, regardless of whether PEP 555 or<br>
> PEP 550 is used. But I'm sure one could decide otherwise.<br>
<br>
</div></div>Please stop using "many things .. would", "most likely" etc.  </blockquote><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">​I can't explain everything, especially not in a single email.​ I will use whatever English words I need. You can also think for yourself––or ask a question.</div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">We have<br>
a very focused discussion here.  If you know of any particular issue,<br>
please demonstrate it with a realistic example.  Otherwise, we only<br>
increase the number of emails and make things harder to track for<br>
everybody.<br>
<br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">I'm not going to (and won't be able to) list all those many use cases. I'd like to keep this more focused too. I'm sure you are well aware of those differences. It's not up to me to decide what `decimal` should do.</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">I'll give you some examples below, if that helps.</div></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
If decimal switches to use PEP 550, there will be no "many things that<br>
*would* change".  The only thing that will change is this:<br>
<br>
  def g():<br>
    with decimal_context(...):<br>
       yield<br>
<br>
  next(g())   # this will no longer leak decimal context to the outer world<br>
<br></blockquote><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">You forgot `yield from g()​`. See also below.</div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
I consider the above a bug fix, because nobody in their right mind<br>
relies on partial iteration of generator expecting that some of it's<br>
internal code would affect your code indirectly.  </blockquote><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">​People use generators for all kinds of things.​ See below.</div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">The only such case<br>
is contextlib.contextmanager, and PEP 550 provides mechanisms to make<br>
generators "leaky" explicitly.<br>
<span class="gmail-HOEnZb"><font color="#888888"><br></font></span></blockquote><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">​That's not the only one.<span style="font-family:arial,sans-serif"> </span></div></div><div><br></div><div><div class="gmail_default" style="font-family:monospace,monospace">​Here's another example:​</div></div><div><br></div><div class="gmail_default" style="font-family:monospace,monospace">​def context_switcher():</div><div class="gmail_default" style="font-family:monospace,monospace">    for c in contexts:</div><div class="gmail_default" style="font-family:monospace,monospace">        decimal.setcontext(c)</div><div class="gmail_default" style="font-family:monospace,monospace">        yield</div><div class="gmail_default" style="font-family:monospace,monospace">​</div><div class="gmail_default" style="font-family:monospace,monospace">ctx_switcher = context_switcher()</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">def next_context():</div><div class="gmail_default" style="font-family:monospace,monospace">    next(ctx_switcher)</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">And one more example:</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">def make_things():</div><div class="gmail_default" style="font-family:monospace,monospace">    old_ctx = None</div><div class="gmail_default" style="font-family:monospace,monospace"><div class="gmail_default">    def first_things_first():</div><div class="gmail_default">        first = compute_first_value()<br></div><div class="gmail_default">        yield first</div><div class="gmail_default"><br></div><div class="gmail_default">        ctx = figure_out_context(first)</div><div class="gmail_default">        nonlocal old_ctx</div><div class="gmail_default">        old_ctx = decimal.getcontext()</div><div class="gmail_default">        decimal.setcontext(ctx)</div><div class="gmail_default"><br></div><div class="gmail_default">        yield get_second_value()</div><div class="gmail_default"><br></div><div class="gmail_default">    def the_bulk_of_things():</div><div class="gmail_default">        return get_bulk()</div><div class="gmail_default"><br></div><div class="gmail_default">    def last_but_not_least():</div><div class="gmail_default">        decimal.set_context(old_ctx)</div><div class="gmail_default">        yield "LAST"</div></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">    yield from first_things_first()</div><div class="gmail_default" style="font-family:monospace,monospace">    yield from the_bulk_of_things()</div><div class="gmail_default" style="font-family:monospace,monospace">    yield from last_but_not_least()</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace">all_things = list(make_things())</div><div class="gmail_default" style="font-family:monospace,monospace"><br></div><div class="gmail_default" style="font-family:monospace,monospace"><br></div></div><div class="gmail_default" style="font-family:monospace,monospace">​––Koos​</div><br clear="all"><div><br></div>-- <br><div class="gmail_signature">+ Koos Zevenhoven + <a href="http://twitter.com/k7hoven" target="_blank">http://twitter.com/k7hoven</a> +</div>
</div></div>