On Thu, Dec 2, 2021 at 6:27 PM Brendan Barnwell email@example.com wrote:
On 2021-12-01 18:35, Chris Angelico wrote:
In my reference implementation, there is no object that stores it; it's simply part of the function. A good parallel is the if/else expression:
x = float("inf") if z == 0 else y/z
Is there an object that represents the if/else expression (or the deferred "y/z" part)? No, although it could be implemented that way if you chose:
This is not a good parallel. There is nothing deferred there. The
entire line is evaluated when it is encountered and you get a result and no part of the if/else expression can ever impact anything else again unless, via some external control flow, execution returns and re-executes the entire line. That is not comparable to a function default, which is STORED and evaluated later independently of the context in which it was originally written (i.e., the function default is re-executed but the function definition itself is not re-executed).
The ternary expression vanishes without a trace by the next line,
leaving only its evaluated result. There would be no use in being able to access some part of it, since the whole (i.e., the ternary expression) is completely finished by the time you would be able to access it. This is not the case with a function definition. The function definition leaves behind a function object, and that function object needs to "know" about the late-bound default as an independent entity so that it can be evaluated later. It is bad for the function to store that late-bound default only in some private format for its exclusive future use without providing any means for other code to access it as a first-class value.
That's exactly why it's such a close parallel. The late-evaluated default is just code, nothing else. It's not "stored" in any way - it is evaluated as part of the function beginning execution.
There is no "first class object" for a late-evaluated default any more than there is one for the "y/z" part of the ternary.