[Python-Dev] Extended Function syntax

Guido van Rossum guido@python.org
Sun, 02 Feb 2003 08:52:33 -0500


[Guido]
> > > I do worry that if my thunks are to be maximally useful, they may end
> > > up having all variables bound through "cells" (as used for nested
> > > scopes) which may give them a reputation of being slow compared to
> > > in-line code, which would limit their popularity for control flow
> > > statements like synchronized().

[Samuele]
> > yes, that worries me to,  it seems at least a likely source of recurring
> > comp.lang.python threads

[Samuele again]
> 'with' syntax does not share the problem, because it is just
> syntax-sugar for a try-finally, not involving thunks.

Right.  Of course, many programmers (the majority? :-) will expect
'with' to do something similar to 'with' in Pascal, VB and JavaScript.
So maybe we'll have to pick a different keyword.  But let's focus on
the semantics of your 'with'.

> Repeating myself, unless one considers the most extreme proposals
> that border macros, thunks [smalltalk-ish anonymous blocks] are
> quite a non-orthogonal addition for a language already with
> functions and closures, generators and 'for'.

Yes, but Python isn't particularly orthogonal anyway.  *If* (and
that's a big if) we can make it fit on all the edges, I don't mind it
being unorthogonal, *if* it also solves a large (better be very large)
class of issues where users would like to extend the language but
currently have to write a lot of extra code, and *if* most of those
issues can't be solved almost as well by something a lot less powerful
(like your 'with').

I think so far I've been thinking mostly about fitting my proposal on
all edges (that's where my discussion of the thunk's scope comes
from).  Maybe I should try to focus more on collecting real-world
examples that are asking for syntactic support, and then try to look
for the simplest way to support most of them.

> [I leave aside generalizing 'class', which is something useful but
> not about control-flow statements and for me a separate problem]
> 
> Much of what:
> 
> do beh(args): (x,...):
>   suite
> 
> can do, can be done already with
> 
> for x,.. in behgen(args): # behgen is a generator that yields where
>                           # beh would invoke the thunk
>   suite
> 
> What is not covered is:
> 
> 1) the case where the thunk passes back some result on invocation by
>    beh using the proposed 'value' direct-to-caller-return statement.
> 2) the case where beh returns a  useful value
>     do e = beh(args): (x,...):
>       suite

And 3) the case where the thunk is saved for later, e.g. when
it is used as a callback or as some other extension of function
definition.  I haven't shown examples of this, but anonymous blocks in
Smalltalk are used for this all the time.  I can't find good docs
about Ruby's iterators that describe whether this is possible or not.

I did find out that Ruby has two iterator syntaxes (do...end and
{...})  that differ in whether they introduce a new scope or not!

> Both could be adressed with the following similar syntax-sugar but
> that defines a usual function instead of a thunk:
> 
> fdo [e=] beh(args): [(x,...):]
>    suite # can contain return
> 
> would be sugar for (or something similar):
> 
> def <anonymous>(x,...):
>   suite
> [e = ] beh(args)(<anonymous>)

Yes, that's one of the cases that I had wanted to cover.

> In this case we don't need to devise new rules for what
> 'break','continue','return' do in the suite. The suite is just the
> body of an anonymous function, 'return' has the usual meaning for a
> function in there. No new concept and rules would be added to the
> language.

> Obviously the suite cannot rebind locals in the surrounding
> function. Given the functional flavor of the construct especially if
> there's an assigmnent e = or beh uses values produced by the suite,
> this can be considered a feature.

It just isn't a good way to implement things like synchronized(),
which really need clean interaction with the environment (through
break, continue, return, and local variable assignment).  (I'm giving
up on 'yield' for now.)

> The addition of 'with' and 'for' plus generators would cover the
> other cases!

Not case (3).

> OTOH what 'return' does in the suite and the fact that the suite is
> not an inline suite can be ambigous at first glance. It is for sure
> a kind of wart.  But this would counterbalance the problem of
> defining/implementing thunks, and what 'break','continue','return'
> would do exactly in them, and the necessity to add 'value' to get
> full expressivity for thunks.

To be continued...

--Guido van Rossum (home page: http://www.python.org/~guido/)