Guido van Rossum wrote:
I've been thinking about this a lot, but haven't made much progess. Here's a brain dump.
I've been thinking about integrating PEP 325 (Resource-Release Support for Generators) into the for-loop code, so that you could replace
[SNIP - using 'for' syntax to delineate the block and resource]
So I think that this is probably not the right thing to pursue,
I totally agree with your reasoning on this.
and we might be better off with something along the lines of PEP 310. The authors of PEP 310 agree; under Open Issues they wrote:
There are some simiralities in concept between 'with ...' blocks and generators, which have led to proposals that for loops could implement the with block functionality[3]. While neat on some levels, we think that for loops should stick to being loops.
(Footnote [3] references the tread that originated PEP 325.)
Perhaps the most important lesson we've learned in this thread is that the 'with' keyword proposed in PEP 310 is redundant -- the syntax could just be
[VAR '=']* EXPR ':' BODY
IOW the regular assignment / expression statement gets an optional colon-plus-suite at the end.
Sure, but is the redundancy *that* bad? You should be able to pick up visually that something is an anonymous block from the indentation but I don't know how obvious it would be. Probably, in the end, this minimal syntax would be fine, but it just seems almost too plain in terms of screaming at me that something special is going on there (the '=' in an odd place just quite cut if for me for my meaning of "special").
So now let's assume we accept PEP 310 with this change. Does this leave any use cases for anonymous blocks uncovered? Ruby's each() pattern is covered by generators; personally I prefer Python's
for var in seq: ...
over Ruby's much-touted
seq.each() {|var| ...}
The try/finally use case is covered by PEP 310. (If you want to combine this with a for-loop in a single operation, you'll need PEP 325.)
The use cases where the block actually returns a value are probably callbacks for things like sort() or map(); I have to admit that I'd rather keep lambda for these (and use named functions for longer blocks) than introduce an anonymous block syntax that can return values! I also note that if you *already* have a comparison function, Ruby's Array sort method doesn't let you pass it in as a function argument; you have to give it a block that calls the comparison function, because blocks are not the same as callables (and I'm not sure that Ruby even *has* callables -- everything seems to be a block).
My tentative conclusion remains: Python doesn't need Ruby blocks. Brian Sabbey ought to come up with more examples rather than arguments why his preferred syntax and semantics are best.
I think I agree with Samuele that it would be more pertinent to put all of this effort into trying to come up with some way to handle cleanup in a generator. -Brett