On Thu, 14 May 2009 09:02:08 am Terry Reedy wrote:
Steven D'Aprano wrote:
On Thu, 14 May 2009 05:18:37 am CTO wrote:
If you thought not reevaluating function expressions was confusing for newbies, wait until you see what making up a new kind of yield will do for them.
Why not just push for some decorators that do this to be included in stdlib? I see the utility, but not the point of adding extra syntax.
Even if a decorator solution can be made to work, it seems to me that the difficulty with a decorator solution is that it is all-or-nothing -- you can decorate the entire parameter list, or none of the parameters, but not some of the parameters. You can bet that people will say they want delayed evaluation of some default arguments and compile-time evaluation of others, in the same function definition.
Not all or nothing, and selection is easy. A decorator could only call callable objects, and could/should be limited to calling function objects or even function objects named '<lambda>'.
Some people don't like writing:
def f(x=SENTINEL): if x is SENTINEL: x = 
and wish to have syntax so they can write something approaching:
def f(x=): ...
but have a fresh  bound to x. You're supporting the syntax:
@call_lambdas # Geremy Condra uses the name 'runtime' def f(x=lambda:): ...
(For the record, I've suggested creating a unary-& operator so that we can write "def f(&x=)" to get late-binding of x.)
If I were to use the proposed late-binding feature, I would want it to be easy to use and obvious. I don't mind having to learn special syntax -- I'm not asking for it to be intuitive or guessable. But having to define the default value as a function (with or without lambda!) *and* call a decorator doesn't seem either easy or obvious. It feels like a kludge designed to get around a limitation of the language. (If you don't like the negative connotations of 'kludge', read it as 'hack' instead.) In other words, it looks like your suggestion is "let's find another idiom for late-binding default arguments" rather than "let's give Python built-in support for optional late-binding of default arguments".
If the first one is your intention, then I'll just walk away from this discussion. I already have a perfectly obvious and explicit idiom for late-binding of default arguments. I don't need a second one, especially one which I find exceedingly inelegant and ugly. If you want to use that in your own code, go right ahead, but I hope it never makes it into any code I ever need to read. -1 from me on any solution which requires both a decorator and special treatment of defaults in the parameter list.
In my opinion, only a solution with built-in support from the compiler is worth supporting. Anything else is a heavyweight, complicated solution for a problem that already has a lightweight, simple solution: use a sentinel. We already have a concise, fast, straightforward idiom which is easily learned and easily written, and while it's not intuitively obvious to newbies, neither is the suggested decorator+lambda solution. We don't need a complicated, verbose, hard-to-explain, hard-to-implement solution as well.