On Thu, Dec 02, 2021 at 11:21:59AM -0800, Brendan Barnwell wrote:
As has happened often in these threads, it seems different people mean different things by "default value".
What you are calling "the default value" is "a thing that is used at call time if no value is passed for the argument". What I am calling "the default value" is "a thing that is noted at definition time to be used later if no value is passed for the argument".
Right-o, I think I get it now! So you are referring to the default *expression*, and you would like it to be an introspectable and maybe even modifiable object, rather than compiled directly in the function body. So given def func(arg=len(seq)+1) you want there to be an actual object representing the expression `len(seq)+1`. An executable object you can poke at, inspect, replace and evaluate, analogous to the way functions already have closures, cells, and code objects rather than just compiling the whole kit and kaboodle into one big binary blob. I'm with you on this. That would be my preference too. But I don't think it would be a deal-breaker for me if there wasn't. I'll push hard for the "independent code object" feature, but if it is impossible as Chris argues, then what cannot be, cannot be. But speaking as somebody with little understanding of the CPython internals, I find it implausible that it is *impossible*. But I have no solid grasp of just how difficult it might be. I can sketch a picture of what I think should happen during the function call process: 1. initialise a namespace "ns" for the function (slots for each local, including the function parameters); 2. populate the local slots for each parameter passed by the caller, including early-bound defaults as needed; 3. for each of the late-bound defaults required: - fetch its code object; - exec it with globals set to the function's globals and locals set to the ns namespace (or a copy of it?) as created in step 1; - if need be, update the real ns from values in the ns-copy; 4. and enter the body of the function. I presume that steps 1, 2 and 4 are already what the interpreter does, or something very close to it. So only 3 is new, and that doesn't seem obviously impossible. It sounds quite like step 4, only using a different code object. In that case, the code objects for the defaults can be independently executed, provided we pass in an appropriate globals and locals namespace. So with the serene self-confidence of somebody who knows that they will never have to do this themselves, I think I can say that none of this sounds hard :-) -- Steve