[Python-Dev] once [was: Simple Switch statementZ] (original) (raw)
Guido van Rossum guido at python.org
Wed Jun 28 18:40:15 CEST 2006
- Previous message: [Python-Dev] once [was: Simple Switch statementZ]
- Next message: [Python-Dev] once [was: Simple Switch statementZ]
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On 6/28/06, Jim Jewett <jimjjewett at gmail.com> wrote:
On 6/25/06, Ka-Ping Yee wrote:
> def f(x): > def g(y): > return y + once x > return g > Does "once" mean not really once here, but "once for each new function > object that's created for g"? Until today, it hadn't really occurred to me that once could mean once per module load rather than once per defining scope.
Funny. Until today (in a different post) it hadn't occurred to me that the proponents of "first-use" switch evaluation were talking about first-use within a function object. I guess the words are ambiguous.
I'm not really a proponent of "once-per-module-scope" semantics in either case, so I'll gladly drop this issue.
I suppose that is reasonable if the values really are constant, but most of the concerns are about what to do when this assumption is violated. It does add a bit of funny flow-control, though.
def f(): def g(): def h(): once x # or switch Normally, there wouldn't be any need to even look inside g (let alone h) at module load time, because the definition of f was run, but the definitions of g and h were not. With module-level once, x is implicitly a module-level variable despite the nesting. Guido: > He specifically wants the latter semantics because it solves the > problem of binding the value of a loop control variable in an outer > scope: Not really. To solve the loop control problem (where the "constant" is certainly not a run-time constant), a once variable also has to be eagerly evaluated. (function definition time?) Nick suggested using once to delay computation of expensive defaults. This means that even if every generated function has its own once variable, none of those variables would be bound to any specific value until they are called -- by which time the loop variable may well be rebound.
Hm. We couldn't use this interpretation of 'once' to capture the value of a loop variable in a nested function. Recall the typical example; the goal is to return a list of argument-less functions that return 0, 1, 2, corresponding to their position in the list. The naive approach is
def index_functions(n): return [(lambda: i) for i in range(n)]
This returns a list of 10 functions that each return the final variable of 'i', i.e. 9.
The current fix is
def index_functions(n): return [(lambda i=i: i) for i in range(n)]
which works but has the disadvantage of returning a list of functions of 0 or 1 argument
I believe at least one poster has pointed out that 'once' (if defined suitably) could be used as a better way to do this:
def index_functions(n): return [(lambda: once i) for i in range(n)]
But delaying the evaluation of the once argument until the function is called would break this, since none of these functions are called until after the loop is over, so the original bug would be back.
Perhaps 'once' is too misleading a name, given the confusion you alluded to earlier. Maybe we could use 'capture' instead? A capture expression would be captured at every function definition time, period. Capture expressions outside functions would be illegal or limited to compile-time constant expressions (unless someone has a better idea). A capture expression inside "if 0:" would still be captured to simplify the semantics (unless the compiler can prove that it has absolutely no side effects).
-- --Guido van Rossum (home page: http://www.python.org/~guido/)
- Previous message: [Python-Dev] once [was: Simple Switch statementZ]
- Next message: [Python-Dev] once [was: Simple Switch statementZ]
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]