On Sat, Oct 30, 2021, 9:40 PM Chris Angelico <ros...@gmail.com> wrote:

> > I'm not sure what I think of a general statement like:
> >
> >     @do_later = fun1(data) + fun2(data)
> >
> > I.e. we expect to evaluate the first class object `do_later` in some
> other context, but only if requested within a program branch where `data`
> is in scope.
>
> If you want to create a "deferred" type, go ahead, but it won't
> conflict with this. There wouldn't be much to gain by restricting it to
> function arguments.
>

I agree there's no gain in restricting deferred computation to function
arguments, but that's EXACTLY what your proposal is.

The way you've written it, it's bound to an assignment, which seems very
> odd. Are you creating an arbitrary object which can be evaluated in some
> other context? Wouldn't that be some sort of constructor call?
>

It's true I don't particularly like the @ syntax. I was just speculating on
continuity with Steven's syntax.

Here's my general proposal, which I actually want, but indeed don't have an
implementation for. I think a soft keyword is best, such as 'defer' or
'later', but let's call it 'delay' for now to avoid the prior hang up on
the word.

(A)

def foo(a: list, size: int = delay len(a)) -> None:
    print("The list has length", size)

Whenever a name is referenced in this future Python, the interpreter first
asks if it is a special delayed object. If not, do exactly what is done
now. However, if it *IS* that special kind of object, instead do something
akin to 'eval()'.

No, the delayed object probably shouldn't just contain a string, but
perhaps a chunk of compiled bytecode.

(B)

So what if we don't want to evaluate the delayed object? Either the same or
a different keyword can do that:

def foo(a: list, size: int = delay len(a)) -> None:
    a.append(42)
    bar(a, delay size)

def bar(a, the_length):
    print("The expanded list has length", the_length)

(C)

What if we want to be more general with delaying (and potentially skipping)
actions?

expensive1 = delay big_computation(data)
expensive2 = delay slow_lookup(data)

def get_answer(data):
    # use globals for the example, less so in practice
    if approximate_compute_cost(data) > 1_000_000:
        return expensive2
    else:
        return expensive1

That's it. It covers everything in your PEP, and great deal more that is
far more important, all using the same syntax.

A few special functions or operations should be able to look at the delayed
object without evaluating it. I'm not sure details, but e.g.

>>> print(delay expensive1)
<Delayed compution of 'big_computation(data)'>
_______________________________________________
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/SU26ANO3ENROSLBLMETSP5GLKC2YE245/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to