syntax for preset locals without using dummy args with defaults

Andrew McGregor andrew at indranet.co.nz
Mon Jan 13 15:18:52 EST 2003


--On Monday, January 13, 2003 18:17:35 +0200 Beni Cherniavsky 
<cben at techunix.technion.ac.il> wrote:

> On 2003-01-11, Bengt Richter wrote:
>
>> 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.
>>
> That's precisely the problem with it.  Consider the lisp/scheme way to
> create functions with preset bindings, (including the "static" behaviour,
> since python's restrictions against changing bindings in outer scopes
> don't apply):
>
> (let ((z zome_expression))
>   (define (foo x y)
>     ...))
>
> Note that the binding is computed when the function is created and not
> when it's run - and that's precisely how it's written.  Currently I can
> blindly assume that the body of a def is not executed immediately.  With
> your preset syntax, I must be wary when reading defs.  It'd be like lisp's
> backquote, a.k.a. semi-quote (which allows special markers inside the
> quoted expression to "unquote" parts of it) that requires more attention
> from the reader than simple quoting.

More like a macro with some quoted some unquoted arguments than partial 
quoting.  Of course, that's exactly what let *is*.

> 1. Most would probably consider this a YAGNI for adding a new keyword.
>
> 2. I see no elegant syntax to allow multiple bindings on the same level
>    (e.g. let and not "poor-man's let*").  For multiple bindings that
>    are not inter-dependent, nesting the lets is visually sub-optimal...
>    The closest thing in python for simultatneous bindings is augmented
>    assignment but it was not designed for this case (no var-value pairs
>    ordering and doesn't continue for many lines.

How about:

with:
    z = some_expression
    z1 = some_other_expression
    # for consistency, should allow this too.
    def quux(bar):
        do_something()
do:
    def foo(x, y=default):
        do_stuff()

One could of course use 'let' instead of 'with'.  This nests, too, and 
provides a tidy way to statically rebind things locally for both 
performance and readability (for instance, the 'self' threads).

This moves the def-time stuff to somewhere that is explicitly done at def 
time, and looks like it.

> 3. The same reason why Python avoids nesting scopes in e.g. a for loop:
>    currently, the scope-creating constructs (def & class) make all
>    inner assignments have a new scope.  So introducing anything that
>    behaves otherwise would make scoping less consistent and "harder to
>    explain".  On the other hand, it would also make it much easier to use
>    and I believe the later should win.

I tend to agree.

Andrew





More information about the Python-list mailing list