On 10 October 2017 at 22:51, Koos Zevenhoven <k7hoven@gmail.com> wrote:
​I see no reason why these two should be equivalent.

There is no "should" about it: it's a brute fact that the two forms *are* currently equivalent for lazy iterators (including generators), and both different from the form that uses eager evaluation of the values before the context change.

Where should enters into the picture is by way of PEP 550 saying that they should *remain* equivalent because we don't have an adequately compelling justification for changing the runtime semantics.

That is, given the following code:

    itr = make_iter()
    with decimal.localcontext() as ctx:
        ctc.prex = 30
        for i in itr:

Right now, today, in 3.6. the calculations in the iterator will use the modified decimal context, *not* the context that applied when the iterator was created. If you want to ensure that isn't the case, you have to force eager evaluation before the context change.

What PEP 550 is proposing is that, by default, *nothing changes*: the lazy iteration in the above will continue to use the updated decimal context by default.

However, people *will* gain a new option for avoiding that: instead of forcing eager evaluation, they'll be able to capture the creation context instead, and switching back to that each time the iterator needs to calculate a new value.

If PEP 555 proposes that we should instead make lazy iteration match eager evaluation semantics by *default*, then that's going to be a much harder case to make because it's a gratuitous compatibility break - code that currently works one way will suddenly start doing something different, and end users will have difficulty getting it to behave the same way on 3.7 as it does on earlier versions.


Nick Coghlan   |   ncoghlan@gmail.com   |   Brisbane, Australia