
On Sun, Oct 24, 2021, 10:11 AM Chris Angelico
Not sure I understand. Your example was something like:
def fn2(thing): a, b = 13, 21 x = 5 print("Thing is:", thing)
def f(x=defer: a + b): a, b = 3, 5 fn2(defer: x) return x
So inside f(), "defer: a + b" will look in f's scope and use the variables a and b from there, but passing a "defer: x" to fn2 will use x from f's scope, and then a and b from fn2's?
Yes, basically as you describe. A "deferred object" is basically just a string that knows to wrap itself in eval() when accessed (maybe Steven's "thunk" is a better term... But definitely something first-class, unlike in Algol). So within fn2() the parameter 'thing' is bound to an object like '<defer eval("a+b")>'. Indeed this means that the 'defer:' or 'thunk' or special symbol spelling, has to decide whether the thing being deferred is already itself a deferred object. If so, just pass along the identical object rather than treat it as a new expression. At least that's what would feel most intuitive to me. But I'm deliberately not pushing a specific syntax. For example, if we didn't want to "reuse" the spelling 'defer:' for both creating and passing a deferred object, we could have different spellings. def f(x=defer: a + b): a, b = 3, 5 fn2(noeval: x) return x ... I don't like that spelling, but just showing the concept.