[Python-Dev] Extended Function syntax

Guido van Rossum guido@python.org
Sat, 01 Feb 2003 21:24:50 -0500


> If I may attempt a summary, given all the use cases that have been
> expressed in this thread, we could have a need for constructions
> whose associated code block is either (1) run immediately or (2)
> passed unexecuted to some constructor; and whose variables are (a)
> in their own namespace or (b) in the parent namespace.

But a mechanism that only allows (2) can trivially be used to provide
(1) as well -- the function to which the thunk is passed simply calls
the thunk.

The real issue is about (a) vs. (b).  I think that it is technically
possible to make the function control this as well, but it may not
execute as fast (unless you compile two versions of the bytecode, or
something similarly wacky).  It is also possible to make the function
control what to do about return, break, and continue (using
pseudo-exceptions), but it definitely feels like a stretch.

> Currently we have 'class' (1a) and, althought currently a bit
> limited in post-processing facilities, 'def' (2a).  I've shown
> contrived examples of (2b) using 'for'.

Actually, I don't think 'for' can really be considered a case of of
(2).  A true version of (2) allows you to save the thunk off in a
global somewhere and call it at a later time.  With 'for' your only
choice is to decide whether to execute it immediately or not; and you
don't get to sniff the contents of the block before executing it.  So
I don't think your contrived examples are worth much.

> The question is whether we want something generic enough for all
> four possible combinations or not, and whether they should still be
> statically distinguishable or not.

That's a good summary.

> If they should not, then the 'thunk' approach is fine, given a way
> to execute a thunk in its original namespace.  This is a well-known
> approach in block-oriented languages, but I agree with Samuele that
> this can be much confusing and for some reason I dislike this
> programming style.  Maybe the reason is that Python has a
> pseudo-declarative look & feel that is incompatible with direct
> manipulation of control flow.  Such a feature would make the life
> impossible for source-processing utilities like code checkers.

I don't think so.  Code checkers make many assumptions that a compiler
isn't allowed to make, and it seems totally reasonable to build
knowledge about popular thunk consumers into the checker.  Just like
GCC has an extension to typecheck printf().

> But if we want the four cases to be statically distinguisable, then
> we might be bound to add various unrelated syntax extensions at
> several places, all of which might come with an associated original
> use case that makes the syntax look like a hack for radically
> different uses (like Just's nice metaclass-based definition of
> properties).

It doesn't have to be that bad.  If, as I argue above, we really only
need to distinguish two cases, we could probably come up with two
fairly neutral syntaxes that cover both ends of the spectrum.

A Pythonic way would be to introduce each with a new keyword:

  # for control flow; <block> is part of surrounding scope
  foo <expr>:
      <block>

  # for definitions; <block> defines a new scope
  # maybe <block> needs formal parameters too
  bar <expr> = <expr>:
      <block>

(I'm not at all sure that only one of these needs the "<expr> ="
part.)

For 'foo', 'do' seems a reasonable keyword; at least,

  do synchronized(mylock):
     BLOCK

looks reasonable enough.  I'm not so comfortable with the leading
contender for 'bar', which seems to be 'def'.

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