On Sun, 26 Jun 2022 at 23:20, Jelle Zijlstra <jelle.zijls...@gmail.com> wrote:
>
>
>
> El sáb, 25 jun 2022 a las 13:44, Chris Angelico (<ros...@gmail.com>) escribió:
>>
>> On Sun, 26 Jun 2022 at 04:41, Brendan Barnwell <brenb...@brenbarn.net> wrote:
>> >         In contrast, what I would want out of deferred evaluation is 
>> > precisely
>> > the ability to evaluate the deferred expression in the *evaluating*
>> > scope (not the definition scope) --- or in a custom provided namespace.
>> >   Whether this evaluation is implicit or explicit is less important to
>> > me than the ability to control the scope in which it occurs.  As others
>> > mentioned in early posts on this thread, this could complicate things
>> > too much to be feasible, but without it I don't really see the point.
>>
>> A custom-provided namespace can already be partly achieved, but
>> working in the evaluating scope is currently impossible and would
>> require some major deoptimizations to become possible.
>>
>> >>> expr = lambda: x + y
>> >>> expr.__code__.co_code
>> b't\x00t\x01\x17\x00S\x00'
>> >>> ns = {"x": 3, "y": 7}
>> >>> eval(expr.__code__, ns)
>> 10
>>
>> This works because the code object doesn't have any locals, so the
>> name references are encoded as global lookups, and eval() is happy to
>> use arbitrary globals. I say "partly achieved" because this won't work
>> if there are any accidental closure variables - you can't isolate the
>> lambda function from its original context and force everything to be a
>> global:
>>
>> >>> def f(x):
>> ...     return lambda: x + y
>> ...
>> >>> expr = f(42)
>> >>> eval(expr.__code__, ns)
>> Traceback (most recent call last):
>>   File "<stdin>", line 1, in <module>
>> TypeError: code object passed to eval() may not contain free variables
>>
>> The mere fact that there's a local variable 'x' means that you can't
>> compile the expression 'x + y'. So maybe there'd need to be some weird
>> trick with class namespaces, but I'm really not sure what would be
>> worth doing.
>>
> Note that in Python 3.11 exec (but not eval) gains the ability to pass an 
> explicit closure:
>
> >>> def f(x):
> ...     return lambda: print(x + y)
> ...
> >>> l = f(1)
> >>> exec(l.__code__, {"y": 3}, closure=(types.CellType(2),))
> 5
>
> This doesn't quite solve the problem being discussed here, but it may help.
>
> This was added in https://github.com/python/cpython/pull/92204. We didn't add 
> it to eval() because there was no use case at the time, but it would be easy 
> to add the same support to eval() too.

Interesting. That would take a bit of extra work (preprocess the
dictionary by checking the function object for its variable names,
then lifting those out into the separate tuple), but it could be done.

ChrisA
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/44JWM546VBY4RHQSQ5THL6N6TBAPZCBZ/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to