
On 2021-10-31 at 14:56:36 +1100, Chris Angelico <rosuav@gmail.com> wrote:
On Sun, Oct 31, 2021 at 2:43 PM <2QdxY4RzWzUUiLuE@potatochowder.com> wrote:
On 2021-10-30 at 18:54:51 -0700, Brendan Barnwell <brenbarn@brenbarn.net> wrote:
On 2021-10-30 18:29, Chris Angelico wrote:
Right. That is a very real difference, which is why there is a very real difference between early-bound and late-bound defaults. But both are argument defaults.
I don't 100% agree with that.
This seems to be the crux of this whole sub-discussion. This whole thing scratches an itch I don't have, likely because of the way I learned to design interfaces on all levels. A week or so ago, I was firmly in Brendan Barnwell's camp. I really don't like how the phrase "default value" applies to PEP-671's late binding, and I'm sure that there will remain cases in which actual code inside the function will be required. But I'm beginning to see the logic behind the arguments (pun intended) for the PEP.
Current versions of the PEP do not use the term "default value" when referring to late binding (or at least, if I've made a mistake there, then please point it out so I can fix it). I'm using the term "default expression", or just "default" (to cover both values and expressions).
I still see anything more complicated than a constant or an extremely simple expression (len(a)? well, ok, maybe; (len(a) if is_prime((len(a)) else next_larger_prime(len(a)))? don't push it) as no longer being a default, but something more serious, but I don't have a better name for it than "computation" or "part of the function" or even "business logic" or "a bad API."
And yes; there will always be cases where you can't define the default with a simple expression. For instance, a one-arg lookup might raise an exception where a two-arg one could return a default value ...
Am I getting ahead of myself, or veering into the weeds, if I ask whether you can catch the exception or what the stacktrace might show? (At this point, that's probably more of a rhetorical question. Again, this is an itch I don't have, so I probably won't use it much.)
The human description language/wording is different; , but what Python spells "default value," Common Lisp spells "initform." Python is currently much less flexible about when and in what context default values are evaluated; PEP-671 attempts to close that gap, but is hampered by certain technical and emotional baggage.
Lisp's execution model is quite different from Python's, but I'd be curious to hear more about this. Can you elaborate?
https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node64.html explains it in great detail with examples; you're interested in &optional, initform, and possibly supplied-p. Summarizing what I think is relevant: (lambda (&optional x)) is a function with an optional parameter called x. Calling that function without a parameter results in x being bound to nil (Lisp's [overloaded] canonical "false"/undefined/null value) in the function body. (lambda (&optional (x 4))) is a function with an optional parameter called x with an initform. Calling that function without a parameter results in x being bound to the value 4 in the function body. Calling that function with a parameter results in x being bound to the value of that parameter. (lambda (&optional (x 4 p))) is a function with an optional parameter called x with an initform and a supplied-p parameter called p. Calling that function without a parameter results in p being bound to nil and x being bound to the value 4 in the function body. Calling that function with a parameter results in p being bound to t (Lisp's canonical "true" value) and x being bound to the value of that parameter. By default (no pun intended), all of that happens at function call time, before the function body begins, but Lisp has ways of forcing evaluation to take place at other times. (lambda (a &optional (hi (length a)))) works as expected; it's a function that takes one parameter called a (presumably a sequence), and an optional parameter called hi (which defaults to the length of a, but can be overridden by the calling code). I am by no means an expert, and again, I tend not to use optional parameters and default values (aka initforms) except in the simplest ways.