[Python-Dev] Re: anonymous blocks

Greg Ewing greg.ewing at canterbury.ac.nz
Tue Apr 26 05:38:48 CEST 2005


Guido van Rossum wrote:

>     with VAR = EXPR:
>         BODY
> 
> This would translate to the following code:
> 
>     it = EXPR
>     err = None
>     while True:
>         try:
>             if err is None:
>                 VAR = it.next()
>             else:
>                 VAR = it.next_ex(err)
>         except StopIteration:
>             break
>         try:
>             err = None
>             BODY
>         except Exception, err: # Pretend "except Exception:" == "except:"
>             if not hasattr(it, "next_ex"):
>                 raise

I like the general shape of this, but I have one or two
reservations about the details.

1) We're going to have to think carefully about the naming of
functions designed for use with this statement. If 'with'
is going to be in there as a keyword, then it really shouldn't
be part of the function name as well. Instead of

   with f = with_file(pathname):
     ...

I would rather see something like

   with f = opened(pathname):
     ...

This sort of convention (using a past participle as a function
name) would work for some other cases as well:

   with some_data.locked():
     ...

   with some_resource.allocated():
     ...

On the negative side, not having anything like 'with' in the
function name means that the fact the function is designed for
use in a with-statement could be somewhat non-obvious. Since
there's not going to be much other use for such a function,
this is a bad thing.

It could also lead people into subtle usage traps such as

   with f = open(pathname):
     ...

which would fail in a somewhat obscure way.

So maybe the 'with' keyword should be dropped (again!) in
favour of

   with_opened(pathname) as f:
     ...

2) I'm not sure about the '='. It makes it look rather deceptively
like an ordinary assignment, and I'm sure many people are going
to wonder what the difference is between

   with f = opened(pathname):
     do_stuff_to(f)

and simply

   f = opened(pathname)
   do_stuff_to(f)

or even just unconsciously read the first as the second without
noticing that anything special is going on. Especially if they're
coming from a language like Pascal which has a much less magical
form of with-statement.

So maybe it would be better to make it look more different:

   with opened(pathname) as f:
     ...

* It seems to me that this same exception-handling mechanism
would be just as useful in a regular for-loop, and that, once
it becomes possible to put 'yield' in a try-statement, people
are going to *expect* it to work in for-loops as well.

Guido has expressed concern about imposing extra overhead on
all for-loops. But would the extra overhead really be all that
noticeable? For-loops already put a block on the block stack,
so the necessary processing could be incorporated into the
code for unwinding a for-block during an exception, and little
if anything would need to change in the absence of an exception.

However, if for-loops also gain this functionality, we end up
with the rather embarrassing situation that there is *no difference*
in semantics between a for-loop and a with-statement!

This could be "fixed" by making the with-statement not loop,
as has been suggested. That was my initial thought as well,
but having thought more deeply, I'm starting to think that
Guido was right in the first place, and that a with-statement
should be capable of looping. I'll elaborate in another post.

> So a block could return a value to the generator using a return
> statement; the generator can catch this by catching ReturnFlow.
> (Syntactic sugar could be "VAR = yield ..." like in Ruby.)

This is a very elegant idea, but I'm seriously worried by the
possibility that a return statement could do something other
than return from the function it's written in, especially if
for-loops also gain this functionality. Intercepting break
and continue isn't so bad, since they're already associated
with the loop they're in, but return has always been an
unconditional get-me-out-of-this-function. I'd feel uncomfortable
if this were no longer true.

-- 
Greg Ewing, Computer Science Dept, +--------------------------------------+
University of Canterbury,	   | A citizen of NewZealandCorp, a	  |
Christchurch, New Zealand	   | wholly-owned subsidiary of USA Inc.  |
greg.ewing at canterbury.ac.nz	   +--------------------------------------+


More information about the Python-Dev mailing list