
On Sat, Oct 30, 2021, 9:40 PM Chris Angelico <rosuav@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)'>