syntax for preset locals without using dummy args with defaults

Bengt Richter bokr at oz.net
Sat Jan 11 20:54:35 CET 2003


On Fri, 10 Jan 2003 21:23:43 -0800, Erik Max Francis <max at alcyone.com> wrote:

>Bengt Richter wrote:
>
>> Let's see how that looks:
>> 
>>     def foo(x, y=default; z=some_expression):
>> 
>> Not bad ;-)
>
>If I understand correctly, you really want these additional parameters
>to be what in C are local variables with static duration.  I certainly
You bring up an interesting point, because default parameter _bindings_
don't really act like C static locals. I.e., with default values, new local
bindings (UIAM) are set up at each call-time, with new call-time bindings to
the def-time-computed default value objects.

This is the behavior I would propose first. For read-only it doesn't make
any difference, but the difference is apparent if you rebind a parameter
name locally. I.e., it doesn't affect the default seen at the next call.

See below [1] for a proposal to add something analogous to C static locals
as well.

>don't object to the concept, but I really don't think that the right
>place for it is in the function declaration, despite the obvious counter
>(and inspiration) that some people use default parameters for just this
>purpose.
>
I agree. It was not my first choice, but I thought it was an easy conceptual
extension of current default-value mal/practice, with a simple spelling.

My first choice would be a new keyword to provide a place other than the parameter
list to specify the def-time code that generates the local bindings in question
(e.g., z above):

     def foo(x, y=default):
         preset: z=some_expression
         ...

IOW, the suite of "preset:" would be compiled to be executed at def-time
rather than call-time. I.e., the code would go into the same context as
the code that evaluates default parameter expressions, not into the body
of the call-time function code. Having a full suite would allow exception handling
and raising in that context, and uncaught exceptions would propagate the
same way def-time default value expression exceptions do.

Of course preset: would allow single-line or indented suites like any compound
statement.

I think if it became a convention to set up bindings to module elements
etc, and do other expensive one-time things in the preset: suite, we would
see both less clutter in the function code body and better speed.

Conceivably on could write a source-transforming optimizer to hoist builtin
dotted module references into the preset suite, as a start. Maybe with
some hints it could hoist other global refs as well. It might be an
alternative to complex runtime global access optimizations.

==[1]============================================================
Persistent local bindings would also be useful. Of course "you can
do it now"(TM) now with classes and instance attributes etc., but you
can say that about a number of other things in Python that have been given
concise "spellings."

What's needed for persistently rebindable local names is a way to
differentiate the names. I think just prefixing a dot would be concise
and simple, e.g.,

     def foo(x, y=default):
         preset:
             z=some_expression
             cache = {}
             pi = __import__('math').pi
             stdout = __import__('sys').stdout
             .firstTime=1
             .counter=0

         # call-time body starts here ...
         .counter+= 1
         if .firstTime: print 'foo: Got my first call.'; firstTime=0
         ...

There, now we have the best of both worlds ;-)

BTW, you could implement .xxx as foo.xxx, but it would be more efficient to
collect all the dot-names and do a __slots__ kind of thing with them, IWT.

Of course, you probably  wouldn't want to use persistent bindings directly
in e.g., library functions but you might want to make a factory function that
returns configured function instances which would have separate persistent locals.

Regards,
Bengt Richter




More information about the Python-list mailing list