On Fri, Dec 03, 2021 at 01:08:50PM +1100, Chris Angelico wrote:
How, with external calling, are you going to know which name references to look up, and where to get their values from?
Isn't the source code available as a string? I will see the names in the expression. Or I will disassemble the code object and inspect its byte-code and/or AST. Or read the documentation. Or maybe the code object will expose those names in a dunder and I can just look at that.
This is already a virtually impossible task in Python, which is why f-strings cannot be implemented as str.format(**something) for any known meaning of "something".
f-strings cannot be implemented as str.format because str.format doesn't evaluate arbitrary expressions.
f'{1000+len(repr(None))}' '1004'
You cannot get your *current* variable set, much less the available variables in some other context.
Why not? The default expression object can record nonlocal variables in a closure, and you can provide your own globals and/or locals. You're saying "can't, impossible" but I could take your function object, extract the code object, disassemble the code to AST or byte-code, extract the portions that represent the default expression, and evaluate that. So not *impossible*, just bloody inconvenient and annoying. (Well, when I say *I could*, I mean *somebody with mad leet AST or byte- code hacking skillz. Not actually me.)
And it is potentially a LOT of unnecessary overhead. Consider this edge case:
def f(a, b=>c:=len(a)): ...
In what context should the name c be bound?
With late-bound defaults, the expression is evaluated at function call time, in the scope of f()'s locals. So c would be a local.
In other words, if you're trying to evaluate b's default externally, you have to set c in a context that doesn't even exist yet. Is that correct?
Yes? You seem to be saying that as if it were some fatal flaw in my proposal. mylocals = {} There. Now the context exists. result = eval(default_expression.__code__, globals(), mylocals())
The third obvious answer is that if either the decision or the implementation is really too hard, then make it a syntax error for now, and revisit it in the future.
Everything's perfectly well defined, save that you can't externally evaluate the defaults.
You keep saying that, but your arguments are not convincing.
You can quite happily use the walrus in a late-bound default, and it'll bind to the function's locals.
Cool :-)
The problem is that you're trying to reference cell variables in a closure that might not even exist yet, so *just in case* you might have nonlocals, you have to construct a closure... or find an existing one. Ill-defined and inefficient.
That doesn't make sense to me. When you compile the default expression, you know what variable names are assigned to with a walrus expression (if any), you know what names exist in the surrounding nonlocal scope (if any), you know what names are parameters. If the default expression doesn't use walrus, doesn't refer to any nonlocal names, and doesn't refer to any other parameters, why would you construct a closure "just in case"? What would you put in it? -- Steve