On Sun, Oct 24, 2021 at 01:16:02PM +1100, Chris Angelico wrote: > What I'm more often seeing is cases that are less obviously a > late-binding, but where the sentinel is replaced with the "real" value > at the point where it's used, rather than up the top of the function.
Got any examples you can share? And is it really a problem if we delay the late-binding to the point where the value is actually needed? Here's a toy example: # Using only early binding. def function(spam, eggs=None, cheese=None): if eggs is None: eggs = cheap_default() # do stuff using eggs ... if condition: return result if cheese is None: cheese = expensive_default() # do stuff using cheese ... return result The cheese parameter only gets used if the processing of spam with eggs fails to give a result. But if cheese is used, the default is expensive. Is it really a problem if we delay evaluating that default to the point where it is needed? So this would be another example where automatic late-binding wouldn't be used. If the default is very expensive, I would stick to manual late- binding using None, and only evaluate it as needed. Maybe this is an argument for some sort of thunk, as in Algol, which is only evaluated at need. Then we could just write: # Assume late-binding with thunks. def function(spam, eggs=cheap_default(), cheese=expensive_default()): # do stuff using eggs ... if condition: return result # do stuff using cheese ... return result and the thunks `cheap_default()` and `expensive_default()` will only be evaluated *if they are actually needed*, rather than automatically when the function is called. To be clear about the semantics, let me illustrate. I am deliberately not using any extra syntax for late-binding. # early binding (the status quo) def func(arg=expression): ... The expression is evaluated when the def statement is run and the func object is created. # late binding (minus any extra syntax) def func(arg=expression): ... The expression is evaluated eagerly when the function is called, if and only if the parameter arg has not been given a value by the caller. # late binding with thunk def func(arg=expression): ... The expression is evaluated only if and when the body of the function attempts to use the value of arg, if the caller has not provided a value. So if the function looks like this: # late binding with a thunk that delays execution until needed def func(flag, arg=1/0): if flag: print("Boom!") return arg return None then func(True) will print Boom! and then raise ZeroDivisionError, and func(False) will happily return None. I have no idea whether thunk-like functionality is workable in Python's execution model without slowing down every object reference, but if it is possible, there could be other really nice use-cases beyond just function defaults. -- Steve _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-le...@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/NW63MNKO7JFQLTP7LTSJQP7W5JB72DGN/ Code of Conduct: http://python.org/psf/codeofconduct/