Cliff Wells wrote:
On Wed, 2008-09-17 at 23:54 -0400, Terry Reedy wrote:
Cliff Wells wrote:
You can accomplish this to some degree by using lambda, You can do it completely as far as I know.
but I'd much prefer something indicated in the function signature than in the calling code.
Given Python's nature as a compiled dynamic language, indications are really needed in both caller and callee, as at present: pass a function and call it. Without an explicit indication at the call site, the compiler would have to compile both direct evaluation and function object creation and the code to select between them at runtime according to an attribute of the function resulting from evaluation of the presumed function expression. This would slow *all* function calls, which are slow enough already. Also, one could not tell what objects get passed to a function without knowing the signature in detail, making code harder to read.
There's one other approach: have two types of functions: <function> and <function-with-lazy-args>.
This is what C and languages sort of have with functions and text macros. Without a name convention (such as CPython uses in its codebase, with macros ALL_CAPS, I believe), one cannot tell, for instance, whether f(x) will or will not result in the passing of 'x' or eval(x). It is what some Lisps used to have -- functions and special functions. Users had to memorized which args of which functions were normal and lazy. There must have been some reason why that was superceded. But to repeat: with Python's dynamic name binding, the compiler cannot in general tell whether the 'f' in 'f(x)' will be bound at runtime to a regular or special function, so as I said above, it would have to code for both possibilities.
Whenever Python encounters a declaration of a function with a lazy argument it creates the latter. This would allow Python to know at runtime how to handle it.
This was already assumed in my original 'select between them at runtime according to an attribute of the function'.
The difference could be transparent to user code (although it might be unappealing to disguise such a difference).
Unless the argument expression has visible side-effects when evaluated. I think there are also namespace issues that you have missed. Consider def f(`a,`b): # ` indicates lazy evaulation, after Lisp's 'quote ..... blaf + f(a+b,c) -3 When f evaluates a bound to 'a+b', it has to *not* resolve 'b' to f's 'b' but to the caller's 'b'. As someone else said, the unevaluated code for 'a+b' is not enough. A full enclosing function is needed. tjr