
On Tue, 26 Oct 2021, Steven D'Aprano wrote:
def func(x=x, y=>x) # or func(x=x, @y=x)
This makes me think of a "real" use-case for assigning all early-bound defaults before late-bound defaults: consider using closure hacks (my main use of early-bound defaults) together with late-bound defaults, as in ``` for i in range(n): def func(arg := expensive(i), i = i): ... ``` I think it's pretty common to put closure hacks at the end, so they don't get in the way of the caller. (The intent is that the caller never specifies those arguments.) But then it'd be nice to be able to use those variables in the late-bound defaults. I can't say this is beautiful code, but it is an application and would probably be convenient. On Tue, 26 Oct 2021, Eric V. Smith wrote:
Among my objections to this proposal is introspection: how would that work? The PEP mentions that the text of the expression would be available for introspection, but that doesn't seem very useful.
I think what would make sense is for code objects to be visible, in the same way as `func.__code__`. But it's definitely worth fleshing out whether: 1. Late-bound defaults are in `func.__defaults__` and `func.__kwdefaults__` -- where code objects are treated as special kind of default values. This seems problematic because we can't distinguish between a late-bound default and an early-bound default that is a code object. or 2. There are new defaults like `func.__late_defaults__` and `func.__late_kwdefaults__`. The issue here is that it's not clear in what order to mix `func.__defaults__` and `func.__late_defaults` (each a tuple). Perhaps most natural is to add a new introspection object, say LateDefault, that can take place as a default value (but can't be used as an early-bound default?), and has a __code__ attribute. --- By the way, another thing missing from the PEP: presumably lambda expressions can also have late-bound defaults? On Tue, 26 Oct 2021, Marc-Andre Lemburg wrote:
Now, it may not be obvious, but the key advantage of such deferred objects is that you can pass them around, i.e. the "defer os.listdir(DEFAULT_DIR)" could also be passed in via another function.
Are deferred code pieces are dynamically scoped, i.e., they are evaluated in whatever scope they end up getting evaluated? That would certainly interesting, but also kind of dangerous (about as dangerous as eval), and I imagine fairly prone to error if they get passed around a lot. If they're *not* dynamically scoped, then I think they're equivalent to lambda, and then they don't solve the default parameter problem, because they'll be evaluated in the function's enclosing scope instead of the function's scope. Erik -- Erik Demaine | edemaine@mit.edu | http://erikdemaine.org/