On Tue, Jun 21, 2022 at 4:28 PM Chris Angelico <rosuav@gmail.com> wrote:
On Wed, 22 Jun 2022 at 08:21, Carl Meyer via Python-ideas
<python-ideas@python.org> wrote:
> On Tue, Jun 21, 2022 at 4:10 PM David Mertz, Ph.D. <david.mertz@gmail.com> wrote:
>> On Tue, Jun 21, 2022 at 5:53 PM Brendan Barnwell <brenbarn@brenbarn.net> wrote:
>>> > In the example, we assume that the built-in function `type()` is special
>>> > in not counting as a reference to the binding for purpose of realizing a
>>> > computation. Alternately, some new special function like `isdeferred()` might be used to
>>> > check for ``Deferred`` objects.
>>> I'll have to ponder my thoughts about the proposal as a whole, but this
>>> particular aspect seems dubious to me.  As I understand it this would
>>> require some fairly deep changes to how evaluation works in Python.
>>> Right now in an expression like `type(blah)`, there isn't any way for
>>> the evaluation of `blah` to depend on the fact that it happens to occur
>>> as an argument to `type`.
>> I absolutely agree that this is a sore point in my first draft.  I could shift the magic from `type()` to `isdeferred()`, but that doesn't really change anything for your examples.  I suppose, that is, unless `isdeferred()` becomes something other than a real function, but more like some sort of macro.  That doesn't make me happy either.
>> However, I *would* like to be able to answer the question "Is this object a DeferredObject?" somehow.  For example, I'd like some way to write code similar to:
>> if isdeferred(expensive_result):
>>     log.debug("The computationally expensive result is not worth calculating here")
>> else:
>>     log.debug(f"We already hit a path that needed the result, and it is {expensive_result}")
>> Any thoughts on what might be the least ugly way to get that?
> I think all it really requires is for isdeferred() to be a builtin implemented in C rather than Python. It will be much better IMO to have isdeferred() returning a bool and not have any deferred object/type visible to Python.

It would have to be non-assignable and probably a keyword. Otherwise,
the exact same issues will keep occurring.

Mmm, you’re right. It would either need to be handled specially in the compiler, or it would have to use the PEP 690 approach of `is_lazy_import(globals(), “name”)` where it takes both the namespace dictionary and the key as string, to avoid triggering reification.

What are the scoping rules for deferred objects? Do they access names
where they are evaluated, or where they are defined? Consider:

def f(x):
    spam = 1

def g():
    spam = 2
    f(later spam)


Does this print 1 or 2?

This is a fundamental and crucial point, and must be settled early.
You cannot defer this. :)

Yes, I agree this is a crucial point, and the answer (which is already somewhat implied by the analogy to lambdas) should be that it closes over the definition scope (just like defining a lambda or online function would.)