Re: [Python-Dev] Re: anonymous blocks
Greg Ewing <[EMAIL PROTECTED]> wrote: > That actually looks pretty reasonable. > > Hmmm. "Patterns of structure." Maybe we could call it a > "struct" statement. > > struct opening(foo) as f: >... > > Then we could confuse both C *and* Ruby programmers at > the same time! :-) And Python programmers who already use the struct module! - Josiah ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
RE: [Python-Dev] Anonymous blocks: Thunks or iterators?
> [Greg Ewing] > > Elegant as the idea behind PEP 340 is, I can't shake > > the feeling that it's an abuse of generators. It seems > > to go to a lot of trouble and complication so you > > can write a generator and pretend it's a function > > taking a block argument. [Guido] > Maybe. You're not the first one saying this and I'm not saying "no" > outright, but I'd like to defend the PEP. > > There are a number of separate ideas that all contribute to PEP 340. > One is turning generators into more general coroutines: continue EXPR > passes the expression to the iterator's next() method (renamed to > __next__() to work around a compatibility issue and because it should > have been called that in the first place), and in a generator this > value can be received as the return value of yield. Incidentally this > makes the generator *syntax* more similar to Ruby (even though Ruby > uses thunks, and consequently uses return instead of continue to pass > a value back). I'd like to have this even if I don't get the block > statement. Completely agree. Maybe we should have PEP 340 push just that, and make a PEP 341 independently for resource-cleanup (which assumes 340)? > [snip] > > The other problem with thunks is that once we think of them as the > anonymous functions they are, we're pretty much forced to say that a > return statement in a thunk returns from the thunk rather than from > the containing function. Doing it any other way would cause major > weirdness when the thunk were to survive its containing function as a > closure (perhaps continuations would help, but I'm not about to go > there :-). > > But then an IMO important use case for the resource cleanup template > pattern is lost. I routinely write code like this: > > def findSomething(self, key, default=None): > self.lock.acquire() > try: > for item in self.elements: > if item.matches(key): > return item > return default > finally: >self.lock.release() > > and I'd be bummed if I couldn't write this as > > def findSomething(self, key, default=None): > block synchronized(self.lock): > for item in self.elements: > if item.matches(key): > return item > return default Okay, you've convinced me. The only way I can think of to get the effect I've been wanting would be to recompile the template function every time that it's executed with a different block. Call it a "Python _re_processor" ;). Although you could memoize the the resultant bytecode, etc., it would still be pretty slow, and you wouldn't be able to alter (rebind) the thunk once you'd entered the caller. Even then, you'd have the cell issues you mentioned, trying to push values from the thunk's original scope. Bah. It's so tempting on the semantic level, but the implementation's a bear. Robert Brewer MIS Amor Ministries [EMAIL PROTECTED] ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: PEP 340 - possible new name for block-statement
Guido van Rossum <[EMAIL PROTECTED]> wrote: > > [Nicolas Fleury] > > I would prefer something that would be > > understandable for a newbie's eyes, even if it fits more with common > > usage than with the real semantics behind it. For example a Boost-like > > keyword like: > > > > scoped EXPR as VAR: > > BLOCK > > Definitely not. In too many languages, a "scope" is a new namespace, > and that's exactly what a block (by whichever name) is *not*. scopeless, unscoped, Scope(tm) (we would be required to use the unicode trademark symbol, of course)... It's way too long, and is too close to a pre-existing keyword, but I think 'finalized' is descriptive. But... finalize EXPR as VAR: BLOCK That reads nice... Maybe even 'cleanup', or 'finalize_after_iteration_without_iter_call' (abbreviated to 'faiwic', of course). <1.0 wink> All right, it's late enough. Enough 'ideas' from me tonight. - Josiah ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
Guido van Rossum wrote: How about, instead of trying to emphasize how different a block-statement is from a for-loop, we emphasize their similarity? If you want to emphasise the similarity, the following syntax and explanation is something that occurred to me during lunch today: Python offers two variants on the basic iterative loop. "for NAME from EXPR:" enforces finalisation of the iterator. At loop completion, a well-behaved iterator is always completely exhausted. This form supports block management operations, that ensure timely release of resources such as locks or file handles. If the values being iterated over are not required, then the statement may be simplified to "for EXPR:". "for NAME in EXPR:" skips the finalisation step. At loop completion, a well-behaved iterator may still contain additional values. This form allows an iterator to be consumed in stages. Regardless of whether you like the above or not, I think the PEP's proposed use of 'as' is incorrect - it looks like the variable should be referring to the expression being iterated over, rather than the values returned from the iterator. Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.skystorm.net ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Anonymous blocks: Thunks or iterators?
Guido van Rossum <[EMAIL PROTECTED]> writes: > [Greg Ewing] >> Elegant as the idea behind PEP 340 is, I can't shake >> the feeling that it's an abuse of generators. It seems >> to go to a lot of trouble and complication so you >> can write a generator and pretend it's a function >> taking a block argument. > > Maybe. You're not the first one saying this and I'm not saying "no" > outright, but I'd like to defend the PEP. This is kind of my point too; I'm not saying that I really prefer the thunk solution, just that I want to see it mentioned. I think the making-generators-more-sexy thing is nice, but I'm think that's almost orthogonal. [...] > Even without a block-statement, these two changes make yield look a > lot like invoking a thunk -- but it's more efficient, since calling > yield doesn't create a frame. > > The main advantage of thunks that I can see is that you can save the > thunk for later, I also find them somewhat easier to understand. > like a callback for a button widget (the thunk then becomes a > closure). You can't use a yield-based block for that (except in > Ruby, which uses yield syntax with a thunk-based implementation). > But I have to say that I almost see this as an advantage: I think > I'd be slightly uncomfortable seeing a block and not knowing whether > it will be executed in the normal control flow or later. Defining an > explicit nested function for that purpose doesn't have this problem > for me, because I already know that the 'def' keyword means its body > is executed later. > > The other problem with thunks is that once we think of them as the > anonymous functions they are, we're pretty much forced to say that a > return statement in a thunk returns from the thunk rather than from > the containing function. Doing it any other way would cause major > weirdness when the thunk were to survive its containing function as a > closure (perhaps continuations would help, but I'm not about to go > there :-). I'm not so sure about this. Did you read this mail: http://mail.python.org/pipermail/python-dev/2005-April/052970.html ? In this proposal, you have to go to some effort to make the thunk survive the block, and I think if weirdness results, that's the programmer's problem. > But then an IMO important use case for the resource cleanup template > pattern is lost. I routinely write code like this: > > def findSomething(self, key, default=None): > self.lock.acquire() > try: > for item in self.elements: > if item.matches(key): > return item > return default > finally: >self.lock.release() > > and I'd be bummed if I couldn't write this as > > def findSomething(self, key, default=None): > block synchronized(self.lock): > for item in self.elements: > if item.matches(key): > return item > return default If you can't write it this way, the thunk proposal is dead. >> I'd like to reconsider a thunk implementation. It >> would be a lot simpler, doing just what is required >> without any jiggery pokery with exceptions and >> break/continue/return statements. It would be easy >> to explain what it does and why it's useful. > > I don't know. In order to obtain the required local variable sharing > between the thunk and the containing function I believe that every > local variable used or set in the thunk would have to become a 'cell' > (our mechanism for sharing variables between nested scopes). Yes. > Cells slow down access somewhat compared to regular local variables. So make them faster. I'm not sure I think this is a good argument. You could also do some analysis and treat variables that are only accessed or written in the block as normal locals. This all makes a block-created thunk somewhat different from an anonymous function, to be sure. But the creating syntax is different, so I don't know if I care (hell, the invoking syntax could be made different too, but I really don't think that's a good idea). > Perhaps not entirely coincidentally, the last example above > (findSomething() rewritten to avoid a return inside the block) shows > that, unlike for regular nested functions, we'll want variables > *assigned to* by the thunk also to be shared with the containing > function, even if they are not assigned to outside the thunk. I swear > I didn't create the example for this purpose -- it just happened. Oh, absolutely. >> On the other hand, a thunk implementation has the >> potential to easily handle multiple block arguments, if >> a suitable syntax could ever be devised. It's hard >> to see how that could be done in a general way with >> the generator implementation. > > Right, but the use cases for multiple blocks seem elusive. If you > really want to have multiple blocks with yield, I suppose we could use > "yield/n" to yield to the n'th block argument, or perhaps yield>>n. > :-) Hmm, it's
Re: [Python-Dev] Anonymous blocks: Thunks or iterators?
Brian Sabbey <[EMAIL PROTECTED]> writes: > It is possible to implement thunks without them creating their own > frame. They can reuse the frame of the surrounding function. So a new > frame does not need to be created when the thunk is called, and, much > like with a yield statement, the frame is not taken down when the > thunk completes running. The implementation just needs to take care > to save and restore members of the frame that get clobbered when the > thunk is running. Woo. That's cute. Cheers, mwh -- SCSI is not magic. There are fundamental technical reasons why it is necessary to sacrifice a young goat to your SCSI chain now and then. -- John Woods ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
Nick Coghlan a écrit : Python offers two variants on the basic iterative loop. "for NAME from EXPR:" enforces finalisation of the iterator. At loop completion, a well-behaved iterator is always completely exhausted. This form supports block management operations, that ensure timely release of resources such as locks or file handles. If the values being iterated over are not required, then the statement may be simplified to "for EXPR:". "for NAME in EXPR:" skips the finalisation step. At loop completion, a well-behaved iterator may still contain additional values. This form allows an iterator to be consumed in stages. Regardless of whether you like the above or not, I think the PEP's proposed use of 'as' is incorrect - it looks like the variable should be referring to the expression being iterated over, rather than the values returned from the iterator. Cheers, Nick. Well, I would go a step further and keep only the for-loop syntax, mainly because I don't understand why there is two syntax for things that's so close we can merge them ! You can simply states that the for-loop call the "__error__" method of the object if available without invalidating any other property of the new for-loop (ie. as defined in the PEP 340). One main reason is a common error could be (using the synchronised iterator introduced in the PEP): for l in synchronised(mylock): do_something() It will compile, run, never raise any error but the lock will be acquired and never released ! Then, I think there is no use case of a generator with __error__ in the for-loop as it is now. So, IMO, it is error-prone and useless to have two different syntaxes for such things. Pierre -- Pierre Barbier de Reuille INRA - UMR Cirad/Inra/Cnrs/Univ.MontpellierII AMAP Botanique et Bio-informatique de l'Architecture des Plantes TA40/PSII, Boulevard de la Lironde 34398 MONTPELLIER CEDEX 5, France tel : (33) 4 67 61 65 77fax : (33) 4 67 61 56 68 ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: anonymous blocks
On 4/29/05, Shane Hathaway <[EMAIL PROTECTED]> wrote: > I think this concept can be explained clearly. I'd like to try > explaining PEP 340 to someone new to Python but not new to programming. > I'll use the term "block iterator" to refer to the new type of > iterator. This is according to my limited understanding. [...] > Is it understandable so far? I like it. Paul. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: anonymous blocks
On 4/29/05, [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote: > > Message: 2 > Date: Thu, 28 Apr 2005 21:56:42 -0600 > From: Shane Hathaway <[EMAIL PROTECTED]> > Subject: Re: [Python-Dev] Re: anonymous blocks > To: [EMAIL PROTECTED] > Cc: Ka-Ping Yee <[EMAIL PROTECTED]>, Python Developers List > > Message-ID: <[EMAIL PROTECTED]> > Content-Type: text/plain; charset=ISO-8859-1 > > > I think this concept can be explained clearly. I'd like to try > explaining PEP 340 to someone new to Python but not new to programming. > I'll use the term "block iterator" to refer to the new type of > iterator. This is according to my limited understanding. > > "Good programmers move commonly used code into reusable functions. > Sometimes, however, patterns arise in the structure of the functions > rather than the actual sequence of statements. For example, many > functions acquire a lock, execute some code specific to that function, > and unconditionally release the lock. Repeating the locking code in > every function that uses it is error prone and makes refactoring difficult. > > "Block statements provide a mechanism for encapsulating patterns of > structure. Code inside the block statement runs under the control of an > object called a block iterator. Simple block iterators execute code > before and after the code inside the block statement. Block iterators > also have the opportunity to execute the controlled code more than once > (or not at all), catch exceptions, or receive data from the body of the > block statement. > > "A convenient way to write block iterators is to write a generator. A > generator looks a lot like a Python function, but instead of returning a > value immediately, generators pause their execution at "yield" > statements. When a generator is used as a block iterator, the yield > statement tells the Python interpreter to suspend the block iterator, > execute the block statement body, and resume the block iterator when the > body has executed. > > "The Python interpreter behaves as follows when it encounters a block > statement based on a generator. First, the interpreter instantiates the > generator and begins executing it. The generator does setup work > appropriate to the pattern it encapsulates, such as acquiring a lock, > opening a file, starting a database transaction, or starting a loop. > Then the generator yields execution to the body of the block statement > using a yield statement. When the block statement body completes, > raises an uncaught exception, or sends data back to the generator using > a continue statement, the generator resumes. At this point, the > generator can either clean up and stop or yield again, causing the block > statement body to execute again. When the generator finishes, the > interpreter leaves the block statement." > > Is it understandable so far? > I've been skipping most of the anonymous block discussion and thus, I only had a very vague idea of what it was about until I read this explanation. Yes, it is understandable -- assuming it's correct :-) Mind you though, I'm not new to python and I've been writing system software for 20+ years. -- Luis P Caamano Atlanta, GA USA ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: anonymous blocks
Hello, Shane Hathaway wrote: > Is it understandable so far? Definitely yes! I had the structure upside-down; your explanation is right on target. Thanks! -- Luis Bruno ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: anonymous blocks
Luis P Caamano wrote: > I've been skipping most of the anonymous block discussion and thus, > I only had a very vague idea of what it was about until I read this > explanation. > > Yes, it is understandable -- assuming it's correct :-) To my surprise, the explanation is now in the PEP. (Thanks, Guido!) Shane ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] PEP 340 - possible new name for block-statement
Nick Coghlan: > Python offers two variants on the basic iterative loop. >"for NAME in EXPR:" skips the finalisation step. At loop > completion, a well-behaved iterator may still contain additional values. > "for NAME from EXPR:" enforces finalisation of the iterator. > ... At loop completion, a well-behaved [finalizing] iterator is > always completely exhausted. (nitpick): "from" isn't really different from "in". Perhaps for NAME inall EXPR: for NAME draining EXPR: for NAME finalizing EXPR:# too hard to spell, because of s/z? (substance): "finalized or not" is a very useful distinction, but I'm not sure it is something the user should have to worry about. Realistically, most of my loops intend to drain the iterator (which the compiler knows because I have no "break:". Regardless of whether I use a break, I still want the iterator cleaned up if it is drained. The only thing this second loop form does is set a flag saying "No, I won't continue -- and I happen to know that no one else ever will either, even if they do have a reference that prevents garbage collection. I'm *sure* they won't use it." That strikes me as a dangerous thing to get in the habit of saying. Why not just agressively run the finalization on both forms when the reference count permits? > This form supports block management operations, And this seems unrelated to finalization. I understand that as an implementation detail, you need to define the finalizers somehow. But the decision to aggressively finalize (in some manner) and desire to pass a block (that could be for finalization) seem like orthogonal issues. -jJ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] About block statement name alternative
How about "bracket" or "bracket_with"? As in: bracket_with synchronized(lock): BLOCK bracket_with opening("/etc/passwd") as f: for line in f: print line.rstrip() bracket_with transactional(db): db.store() bracket_with auto_retry(3, IOError): f = urllib.urlopen("http://python.org/peps/pep-0340.html";) print f.read() block_with synchronized_opening("/etc/passwd", myLock) as f: for line in f: print line.rstrip() def synchronized_opening(lock, filename, mode="r"): bracket_with synchronized(lock): bracket_with opening(filename) as f: yield f bracket_with synchronized_opening("/etc/passwd", myLock) as f: for line in f: print line.rstrip() Or for that matter, "block_with", as in: block_with transactional(db): db.store() -- Luis P Caamano Atlanta, GA USA ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] PEP 340: What is "ret" in block statement semantics?
PEP 340 describes the block statement translation as: itr = EXPR1 val = arg = None ret = False while True: try: VAR1 = next(itr, arg) except StopIteration: if ret: return val if val is not None: raise val break try: val = arg = None ret = False BLOCK1 except Exception, val: arg = StopIteration() It uses a variable "ret" that is always False. If it does manage to take on a True value, a return statement is executed. How does ret become True? What's meaning of return in this context? Something seems amiss. Skip ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] PEP 340: What is "ret" in block statement semantics?
me> It uses a variable "ret" that is always False. Gaack. Please ignore. Skip ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
Pierre Barbier de Reuille wrote: One main reason is a common error could be (using the synchronised iterator introduced in the PEP): for l in synchronised(mylock): do_something() It will compile, run, never raise any error but the lock will be acquired and never released ! It's better than that. With the code above, CPython is actually likely to release the lock when the loop exits. Change the code to the below to ensure the lock doesn't get released: sync = synchronised(mylock): for l in sync: do_something() Then, I think there is no use case of a generator with __error__ in the for-loop as it is now. So, IMO, it is error-prone and useless to have two different syntaxes for such things. Hmm. This does make PJE's suggestion of requiring a decorator in order to flag generators for finalisation a little more appealing. Existing generators (without the flag) would not be cleaned up, preserving backwards compatibility. Generators with the flag would allow resource clean up. In this case of no new statement syntax, it would probably make more sense to refer to iterators that get cleaned up as finalised iterators, and a builtin with the obvious name would be: def finalised(obj): obj.__finalise__ = True # The all important flag! return obj The syntax below would still be horrible: for f in opening(filename): for line in f: # process line But such ugliness could be fixed by pushing the inner loop inside the block iterator: for line in opened(filename): # process line @finalised def opened(filename): f = open(filename) try: for line in f: yield line finally: f.close() Then, in Py3K, finalisation could simply become the default for loop behaviour. However, the '__finalise__' flag would result in some impressive code bloat, as any for loop would need to expand to: itr = iter(EXPR1) if getattr(itr, "__finalise__", False): # Finalised semantics #I'm trying to channel Guido here. #This would really look like whatever the PEP 340 block statement #semantics end up being val = arg = None ret = broke = False while True: try: VAR1 = next(itr, arg) except StopIteration: BLOCK2 break try: val = arg = None ret = False BLOCK1 except Exception, val: itr.__error__(val) if ret: try: itr.__error__(StopIteration()) except StopIteration: pass return val else: # Non-finalised semantics arg = None while True: try: VAR1 = next(itr, arg) except StopIteration: BLOCK2 break arg = None BLOCK1 The major danger I see is that you could then write a generator containing a yield inside a try/finally, _without_ applying the finalisation decorator. Leading to exactly the problem described above - the lock (or whatever) is never cleaned up, because the generator is not flagged for finalisation. In this scenario, even destruction of the generator object won't help. Cheers, Nick. P.S. I think PEP 340's proposed for loop semantics are currently incorrect, as BLOCK2 is unreachable. It should look more like the non-finalised semantics above (with BLOCK2 before the break in the except clause) -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.skystorm.net ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
Jim Jewett wrote: Why not just agressively run the finalization on both forms when the reference count permits? So the iterator is always finalised if the for loop has the only reference? Two problems I can see there is that naming the target of the for loop would prevent it being finalised, and that this would make life interesting when the Jython or IronPython folks catch up to Python 2.5. . . The finalised/not finalised aspect definitely seems to be the key behavioural distinction between the two forms, though. And I think there are legitimate use cases for a non-finalised form. Things like: for line in f: if end_of_header(line): break # process header line for line in f: # process body line With only a finalised form of iteration available, this would need to be rewritten as something like: def header(f): line = next(f) while not end_of_header(line): line = next(f, yield line) for line in header(f): # process header line for line in f: # process body line Considering the above, I actually have grave reservations about *ever* making finalisation the default behaviour of for loops - if I break out of a standard for loop before exhausting the iterator, I would expect to be able to resume the iterator afterwards, rather than having it flushed behind my back. Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.skystorm.net ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
Nick Coghlan a écrit : Pierre Barbier de Reuille wrote: One main reason is a common error could be (using the synchronised iterator introduced in the PEP): for l in synchronised(mylock): do_something() It will compile, run, never raise any error but the lock will be acquired and never released ! It's better than that. With the code above, CPython is actually likely to release the lock when the loop exits. Change the code to the below to ensure the lock doesn't get released: sync = synchronised(mylock): for l in sync: do_something() Well indeed, but this will be an implementation-dependant behaviour ... Then, I think there is no use case of a generator with __error__ in the for-loop as it is now. So, IMO, it is error-prone and useless to have two different syntaxes for such things. [...] The major danger I see is that you could then write a generator containing a yield inside a try/finally, _without_ applying the finalisation decorator. Leading to exactly the problem described above - the lock (or whatever) is never cleaned up, because the generator is not flagged for finalisation. In this scenario, even destruction of the generator object won't help. Mmmmh ... why introduce a new flag ? Can't you just test the presence of the "__error__" method ? This would lift your problem wouldn't it ? Cheers, Nick. P.S. I think PEP 340's proposed for loop semantics are currently incorrect, as BLOCK2 is unreachable. It should look more like the non-finalised semantics above (with BLOCK2 before the break in the except clause) -- Pierre Barbier de Reuille INRA - UMR Cirad/Inra/Cnrs/Univ.MontpellierII AMAP Botanique et Bio-informatique de l'Architecture des Plantes TA40/PSII, Boulevard de la Lironde 34398 MONTPELLIER CEDEX 5, France tel : (33) 4 67 61 65 77fax : (33) 4 67 61 56 68 ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Anonymous blocks: Thunks or iterators?
On Thu, Apr 28, 2005, Brian Sabbey wrote: > > It is possible to implement thunks without them creating their own frame. > They can reuse the frame of the surrounding function. So a new frame does > not need to be created when the thunk is called, and, much like with a > yield statement, the frame is not taken down when the thunk completes > running. The implementation just needs to take care to save and restore > members of the frame that get clobbered when the thunk is running. > > Cells would of course not be required if the thunk does not create its own > frame. Maybe. It's not clear whether your thunks are lexical (I haven't been following the discussion closely). If it's not lexical, how do locals get handled without cells? -- Aahz ([EMAIL PROTECTED]) <*> http://www.pythoncraft.com/ "It's 106 miles to Chicago. We have a full tank of gas, a half-pack of cigarettes, it's dark, and we're wearing sunglasses." "Hit it." ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
On Fri, Apr 29, 2005, Nick Coghlan wrote: > > If you want to emphasise the similarity, the following syntax and > explanation is something that occurred to me during lunch today: We don't want to emphasize the similarity. > Python offers two variants on the basic iterative loop. > > "for NAME from EXPR:" enforces finalisation of the iterator. At loop > completion, a well-behaved iterator is always completely exhausted. This > form supports block management operations, that ensure timely release of > resources such as locks or file handles. > If the values being iterated over are not required, then the statement > may be simplified to "for EXPR:". > > "for NAME in EXPR:" skips the finalisation step. At loop completion, a > well-behaved iterator may still contain additional values. This form allows > an iterator to be consumed in stages. -1 -- the Zen of Python implies that we should be able to tell which construct we're using at the beginning of the line. -- Aahz ([EMAIL PROTECTED]) <*> http://www.pythoncraft.com/ "It's 106 miles to Chicago. We have a full tank of gas, a half-pack of cigarettes, it's dark, and we're wearing sunglasses." "Hit it." ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
On 4/28/05, Guido van Rossum <[EMAIL PROTECTED]> wrote: > How about, instead of trying to emphasize how different a > block-statement is from a for-loop, we emphasize their similarity? > > A regular old loop over a sequence or iterable is written as: > > for VAR in EXPR: > BLOCK > > A variation on this with somewhat different semantics swaps the keywords: > > in EXPR for VAR: > BLOCK > > If you don't need the variable, you can leave the "for VAR" part out: > > in EXPR: > BLOCK > > Too cute? :-) If you want to truly confuse the Ruby folks, you could go for something like: { EXPR } VAR: BLOCK ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
Nick Coghlan <[EMAIL PROTECTED]> wrote: > Then, in Py3K, finalisation could simply become the default for loop > behaviour. > However, the '__finalise__' flag would result in some impressive code bloat, > as > any for loop would need to expand to: > > itr = iter(EXPR1) > if getattr(itr, "__finalise__", False): > # Finalised semantics > #I'm trying to channel Guido here. > #This would really look like whatever the PEP 340 block statement > #semantics end up being > val = arg = None > ret = broke = False > while True: > try: > VAR1 = next(itr, arg) > except StopIteration: > BLOCK2 > break > try: > val = arg = None > ret = False > BLOCK1 > except Exception, val: > itr.__error__(val) > if ret: > try: > itr.__error__(StopIteration()) > except StopIteration: > pass > return val The problem is that BLOCK2 is executed within the while loop (the same problem I had with a fix I offered), which may contain a break for breaking out of a higher-level loop construct. Here's one that works as you intended (though perhaps I'm being a bit to paranoid about the __error__ attribute)... val = arg = None ret = ex_block_2 = False while True: try: VAR1 = next(itr, arg) except StopIteration: ex_block_2 = True break try: val = arg = None ret = False BLOCK1 except Exception, val: if hasattr(itr, '__error__): itr.__error__(val) if ret: try: if hasattr(itr, '__error__'): itr.__error__(StopIteration()) except StopIteration: pass return val if ex_block_2: BLOCK2 > P.S. I think PEP 340's proposed for loop semantics are currently incorrect, > as > BLOCK2 is unreachable. It should look more like the non-finalised semantics > above (with BLOCK2 before the break in the except clause) Indeed, I also mentioned this on Wednesday. - Josiah ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
At 09:38 AM 4/29/05 -0700, Aahz wrote: -1 -- the Zen of Python implies that we should be able to tell which construct we're using at the beginning of the line. Hm, maybe we should just use "@", then. :) e.g. @synchronized(self): @with_file("foo") as f: # etc. Although I'd personally prefer a no-keyword approach: synchronized(self): with_file("foo") as f: # etc. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
Nick Coghlan <[EMAIL PROTECTED]> wrote: > # Non-finalised semantics > arg = None > while True: > try: > VAR1 = next(itr, arg) > except StopIteration: > BLOCK2 > break > arg = None > BLOCK1 And that bad boy should be... # Non-finalised semantics ex_block_2 = False arg = None while True: try: VAR1 = next(itr, arg) except StopIteration: ex_block_2 = True break arg = None BLOCK1 if ex_block_2: BLOCK2 Josiah Carlson wrote: > Indeed, I also mentioned this on Wednesday. Though I was somewhat incorrect as code examples I offered express the actual intent. - Josiah ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
[Phillip J. Eby] > Although I'd personally prefer a no-keyword approach: > > synchronized(self): > with_file("foo") as f: > # etc. I'd like that too, but it was shot down at least once. Maybe we can resurrect it? opening("foo") as f: # etc. is just a beauty! -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] Anonymous blocks: Thunks or iterators?
Brian Sabbey: > It is possible to implement thunks without them creating their own > frame. They can reuse the frame of the surrounding function ... > The implementation just needs to take care > to save and restore members of the frame that get clobbered when the > thunk is running. Michael Hudson: > Woo. That's cute. It *sounds* horrendous, but is actually pretty reasonable. Conceptually, a thunk replaces a suite in the caller. Most frame members are intended to be shared, and changes should be visible -- so they don't have to (and shouldn't) be restored. The only members that need special attention are (f_code, f_lasti) and possibly (f_blockstack, f_iblock). (f_code, f_lasti) would need to be replaced with a stack of pairs. Finishing a code string would mean popping this stack, rather than popping the whole frame. Since a completed suite leaves the blockstack where it started, (f_blockstack, f_iblock) *can* be ignored, though debugging and CO_MAXBLOCKS both *suggest* replacing the pair with a stack of pairs. -jJ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
On 4/29/05, Guido van Rossum <[EMAIL PROTECTED]> wrote: > [Phillip J. Eby] > > Although I'd personally prefer a no-keyword approach: > > > > synchronized(self): > > with_file("foo") as f: > > # etc. > > I'd like that too, but it was shot down at least once. Maybe we can > resurrect it? > > opening("foo") as f: > # etc. > > is just a beauty! I agree, but does this then work: x = opening("foo") ...stuff... x as f: # etc ? And if not, why not? And if yes, what happens if "stuff" raises an exception? ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
> I agree, but does this then work: > > x = opening("foo") > ...stuff... > x as f: ># etc > > ? And if not, why not? And if yes, what happens if "stuff" raises an > exception? Forget it -- the above is probably addressed by the PEP and doesn't really depend on whether there's a kw or not. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
On Fri, Apr 29, 2005, Guido van Rossum wrote: > [Phillip J. Eby] >> >> Although I'd personally prefer a no-keyword approach: >> >> synchronized(self): >> with_file("foo") as f: >> # etc. > > I'd like that too, but it was shot down at least once. Maybe we can > resurrect it? > > opening("foo") as f: > # etc. I'm still -1 for the same reason I mentioned earlier: function calls spanning multiple lines are moderately common in Python code, and it's hard to distinguish these cases because multi-line calls usually get indented like blocks. -- Aahz ([EMAIL PROTECTED]) <*> http://www.pythoncraft.com/ "It's 106 miles to Chicago. We have a full tank of gas, a half-pack of cigarettes, it's dark, and we're wearing sunglasses." "Hit it." ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] next(arg) was: Anonymous blocks: Thunks or iterators?
Guido van Rossum: > One [of many separate ideas in PEP 340] is turning generators > into more general coroutines: continue EXPR passes the expression > to the iterator's next() method ... I would have been very happy with that a week ago. Seeing the specific implementation changed my mind. The caller shouldn't know what state the generator is in, so the passed-in-message will be the same regardless of which yield accepts it. Unless I have a single-yield generator, this means I end up writing boilerplate code to accept and process the arg at each yield. I don't want more boilerplate. > Even without a block-statement, these two changes make yield look a > lot like invoking a thunk Though it feels backwards to me; yield is returning control to something that already had to coordinate the thunks itself. -jJ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
At 10:42 AM 4/29/05 -0700, Aahz wrote: On Fri, Apr 29, 2005, Guido van Rossum wrote: > [Phillip J. Eby] >> >> Although I'd personally prefer a no-keyword approach: >> >> synchronized(self): >> with_file("foo") as f: >> # etc. > > I'd like that too, but it was shot down at least once. Maybe we can > resurrect it? > > opening("foo") as f: > # etc. I'm still -1 for the same reason I mentioned earlier: function calls spanning multiple lines are moderately common in Python code, and it's hard to distinguish these cases because multi-line calls usually get indented like blocks. But the indentation of a multi-line call doesn't start with a colon. Or are you saying you're concerned about things like: opening( blah, blah, foo, wah=flah ) as fidgety, widgety, foo: sping() Which is quite ugly, to be sure, but then I don't see where adding an extra keyword helps. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Anonymous blocks: Thunks or iterators?
[Michael Hudson] > I think the making-generators-more-sexy thing is nice, but I'm think > that's almost orthogonal. Not entirely. I agree that "continue EXPR" calling next(EXPR) which enables yield-expressions is entirely orthogonal. But there are already two PEPs asking for passing exceptions and/or cleanup into generators and from there it's only a small step to using them as resource allocation/release templates. The "small step" part is important -- given that we're going to do that work on generators anyway, I expect the changes to the compiler and VM to support the block statement are actually *less* than the changes needed to support thunks. No language feature is designed in isolation. > Did you read this mail: > > http://mail.python.org/pipermail/python-dev/2005-April/052970.html > > ? In this proposal, you have to go to some effort to make the thunk > survive the block, and I think if weirdness results, that's the > programmer's problem. It's not a complete proposal though. You say "And grudgingly, I guess you'd need to make returns behave like that anyway" (meaning they should return from the containing function). But you don't give a hint on how that could be made to happen, and I expect that by the time you've figured out a mechanism, thunks aren't all that simple any more. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
Jim Jewett wrote: Nick Coghlan: Python offers two variants on the basic iterative loop. "for NAME in EXPR:" skips the finalisation step. At loop completion, a well-behaved iterator may still contain additional values. "for NAME from EXPR:" enforces finalisation of the iterator. ... At loop completion, a well-behaved [finalizing] iterator is always completely exhausted. (nitpick): "from" isn't really different from "in". Perhaps for NAME inall EXPR: for NAME draining EXPR: for NAME finalizing EXPR:# too hard to spell, because of s/z? (substance): "finalized or not" is a very useful distinction, but I'm not sure it is something the user should have to worry about. Realistically, most of my loops intend to drain the iterator (which the compiler knows because I have no "break:". Regardless of whether I use a break, I still want the iterator cleaned up if it is drained. The only thing this second loop form does is set a flag saying "No, I won't continue -- and I happen to know that no one else ever will either, even if they do have a reference that prevents garbage collection. I'm *sure* they won't use it." That strikes me as a dangerous thing to get in the habit of saying. Why not just agressively run the finalization on both forms when the reference count permits? This form supports block management operations, And this seems unrelated to finalization. I understand that as an implementation detail, you need to define the finalizers somehow. But the decision to aggressively finalize (in some manner) and desire to pass a block (that could be for finalization) seem like orthogonal issues. -jJ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/rrr%40ronadam.com How about 'serve' as in a server of items from a service? serve NAME from EXPR: I think this is more descriptive of what it does and will make it easier to explain. It also implies the correct relationship between the block, the name, and the expression. I think 'block' and 'with' are both *way* too general. The problem I see with 'block' is that the term is often used as a general term to describe the body of other statements while, for, if, ... etc. The generator in this case could be called a 'server' which would distinguish it from a normal genrator. By using 'serve' as a keyword, you can then refer to the expression as a whole as a 'service' or a 'resouce manager'. And a simple description of it would be A SERVE statement serves NAME(s) from a SERVER to the following statement block. (Details of how to use SERVE blocks and SERVERS.) Ron Adam ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] next(arg) was: Anonymous blocks: Thunks or iterators?
[Guido van Rossum] > > One [of many separate ideas in PEP 340] is turning generators > > into more general coroutines: continue EXPR passes the expression > > to the iterator's next() method ... [Jim Jewett] > I would have been very happy with that a week ago. Seeing the > specific implementation changed my mind. > > The caller shouldn't know what state the generator is in, so the > passed-in-message will be the same regardless of which yield > accepts it. Unless I have a single-yield generator, this means > I end up writing boilerplate code to accept and process the arg > at each yield. I don't want more boilerplate. I think your premise is wrong. When necessary (which it usually won't be) the caller can tell the generator's state from the last thing it yielded. Coroutines can easily define a protocol based on this if needed. Anyway, single-yield generators are by far the majority. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
[Ron Adam] > How about 'serve' as in a server of items from a service? No, please. This has way too strong connotations with network protocols. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Anonymous blocks: Thunks or iterators?
Jim Jewett wrote: The only members that need special attention are (f_code, f_lasti) and possibly (f_blockstack, f_iblock). You don't even need to take care of f_code. The thunk and its surrounding function can share the same code. The thunk gets compiled into the function the same way the body of a for loop would. (f_code, f_lasti) would need to be replaced with a stack of pairs. Finishing a code string would mean popping this stack, rather than popping the whole frame. There doesn't need to be a stack; each thunk can store its own f_lasti. One also needs to store f_back, and, to avoid exception weirdness, f_exc_XXX. In this way, calling the thunk is much like resuming a generator. -Brian ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] PEP 340: syntax suggestion - try opening(filename) as f:
I don't know whether it's true for all the PEP 340 use cases, but the all the current examples would read very naturally if the block-template could be specified in an extended try statement: 1. A template for ensuring that a lock, acquired at the start of a block, is released when the block is left: try with_lock(myLock): # Code here executes with myLock held. The lock is # guaranteed to be released when the block is left (even # if by an uncaught exception). 2. A template for opening a file that ensures the file is closed when the block is left: try opening("/etc/passwd") as f: for line in f: print line.rstrip() 3. A template for committing or rolling back a database transaction: try transaction(mydb): 4. A template that tries something up to n times: try auto_retry(3): f = urllib.urlopen("http://python.org/peps/pep-0340.html";) print f.read() 5. It is possible to nest blocks and combine templates: try with_lock(myLock): try opening("/etc/passwd") as f: for line in f: print line.rstrip() Michael ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] Anonymous blocks: Thunks or iterators?
Guido van Rossum: > -- but it's more efficient, since calling yield doesn't create a frame. Neither should a thunk. > The other problem with thunks is that once we think of them as the > anonymous functions they are, we're pretty much forced to say that a > return statement in a thunk returns from the thunk rather than from > the containing function. Why should a thunk be a function? We already have first class functions. What we're missing is a way to pass around a suite. def foo(a): if a > 4: b = a c = process(a) # thunk line 1 print a # thunk line 2 return # thunk line 3 else: a.something() We don't have a good way to package up "c = process(a); print a; return" The return should exit the whole function, not just (part of) the if clause. Greg: >> I'd like to reconsider a thunk implementation. It >> would be a lot simpler, doing just what is required >> without any jiggery pokery with exceptions and >> break/continue/return statements. It would be easy >> to explain what it does and why it's useful. > I don't know. In order to obtain the required local variable sharing > between the thunk and the containing function I believe that every > local variable used or set in the thunk would have to become a 'cell' > (our mechanism for sharing variables between nested scopes). Cells only work if you have a complete set of names at compile-time. Your own resource-example added "item" to the namespace inside a block. If you don't know which blocks could be used with a pattern, cells are out. That said, the compiler code is already two-pass. Once to find names, and another time to resolve them. This just means that for thunks (and functions that call them) the adjustment will be to LOAD_NAME instead of getting a LOAD_FAST index. -jJ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: anonymous blocks
On Thu, 28 Apr 2005, Shane Hathaway wrote: [...] > I think this concept can be explained clearly. I'd like to try > explaining PEP 340 to someone new to Python but not new to programming. [...snip explanation...] > Is it understandable so far? Yes, excellent. Speaking as somebody who scanned the PEP and this thread and only half-understood either, that was quite painless to read. Still not sure whether thunks or PEP 340 are better, but I'm at least confused on a higher level now. John ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
Guido van Rossum wrote: [Ron Adam] How about 'serve' as in a server of items from a service? No, please. This has way too strong connotations with network protocols. Errr... you're right of course... :-/ (I was thinking *way* to narrow.) I think the context is correct, just need a synonym that isn't already used. provide, provider supply, supplier dispense, dispenser deal, dealer deliver, deliveror or parcel, meter, dish, give, dole, offer, cede... Maybe barrow from a different language? Ron Adam ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Anonymous blocks: Thunks or iterators?
On 4/29/05, Brian Sabbey <[EMAIL PROTECTED]> wrote: > Jim Jewett wrote: > > The only members that need special attention are (f_code, f_lasti) > > and possibly (f_blockstack, f_iblock). > You don't even need to take care of f_code. The thunk and its surrounding > function can share the same code. The thunk gets compiled into the > function the same way the body of a for loop would. This only works if you already know what the thunk's code will be when you compile the function. (Just splicing it in messes up jump targets.) > One also needs to store f_back, and, to avoid exception weirdness, > f_exc_XXX. f_back lists the previous stack frame (which shouldn't change during a thunk[1]), and f_exc_XXX is for the most recent exception -- I don't see any reason to treat thunks differently from loop bodies in that regard. [1] If the thunk calls another function (that needs its own frame), then that is handled the same as any regular function call. -jJ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] PEP 340: syntax suggestion - try opening(filename) as f:
Michael Spencer: > I don't know whether it's true for all the PEP 340 use cases, but the all the > current examples would read very naturally if the block-template could be > specified in an extended try statement: >> 1. A template for ensuring that a lock, acquired at the start of a >>block, is released when the block is left: > try with_lock(myLock): > # Code here executes with myLock held. The lock is > # guaranteed to be released when the block is left (even > # if by an uncaught exception). So we would have try ... finally, try ... except, and try (no close). It works for me, and should be backwards-compatible. The cases where it doesn't work as well are (1) You want to insert several different suites. But the anonymous yield syntax doesn't work well for that either. (That is one of the arguments for thunks instead of generator abuse.) (2) You really do want to loop over the suite. Try doesn't imply a loop. But this is a *good* thing. Resources are not loops, and you can always make the loop explicit as iteration over the resource def opener(file): f=open(file) try: yield f finally: f.close() try opener(file) as f: for line in f: process(line) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
On Fri, Apr 29, 2005, Phillip J. Eby wrote: > At 10:42 AM 4/29/05 -0700, Aahz wrote: >>On Fri, Apr 29, 2005, Guido van Rossum wrote: >>> [Phillip J. Eby] Although I'd personally prefer a no-keyword approach: synchronized(self): with_file("foo") as f: # etc. >>> >>> I'd like that too, but it was shot down at least once. Maybe we can >>> resurrect it? >>> >>> opening("foo") as f: >>> # etc. >> >>I'm still -1 for the same reason I mentioned earlier: function calls >>spanning multiple lines are moderately common in Python code, and it's >>hard to distinguish these cases because multi-line calls usually get >>indented like blocks. > > But the indentation of a multi-line call doesn't start with a colon. Neither does the un-keyworded block. It starts with a colon on the end of the previous line. I thought part of the point of Python was to minimize reliance on punctuation, especially where it's not clearly visible? -- Aahz ([EMAIL PROTECTED]) <*> http://www.pythoncraft.com/ "It's 106 miles to Chicago. We have a full tank of gas, a half-pack of cigarettes, it's dark, and we're wearing sunglasses." "Hit it." ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] Re: PEP 340 - possible new name for block-statement
Robin Munn wrote: [snip] Another possibility just occurred to me. How about "using"? ~using EXPR as VAR: ~BLOCK Examples from PEP 340: == def synchronized(lock): ... using synchronized(myLock): ... = (+0) def opening(filename, mode="r"): ... using opening("/etc/passwd") as f: ... = (+1) def auto_retry(n=3, exc=Exception): ... using auto_retry(3, IOError): ... = (+1) def synchronized_opening(lock, filename, mode="r"): ... using synchronized_opening("/etc/passwd", myLock) as f: ... = (+1) A.R. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] Re: PEP 340 - possible new name for block-statement
Guido van Rossum wrote: [Nicolas Fleury] scoped EXPR as VAR: BLOCK Definitely not. In too many languages, a "scope" is a new namespace, and that's exactly what a block (by whichever name) is *not*. Humm... what about "context"? context EXPR as VAR: BLOCK I may answer the question myself, but is an alternative syntax without an indentation conceivable? (yes, even since the implicit block could be run multiple times). Because in that case, a keyword like "block" would not look right. It seems to me that in most RAII cases, the block could end at the end of the current block and that's fine, and over-indentation can be avoided. However, I realize that the indentation makes more sense in the context of Python and removes some magic that would be natural for a C++ programmer used to presence of stack... Ok, I answer my question, but "context" still sounds nicer to me than "block";) Regards, Nicolas ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
At 12:05 PM 4/29/05 -0700, Aahz wrote: On Fri, Apr 29, 2005, Phillip J. Eby wrote: > At 10:42 AM 4/29/05 -0700, Aahz wrote: >>On Fri, Apr 29, 2005, Guido van Rossum wrote: >>> [Phillip J. Eby] Although I'd personally prefer a no-keyword approach: synchronized(self): with_file("foo") as f: # etc. >>> >>> I'd like that too, but it was shot down at least once. Maybe we can >>> resurrect it? >>> >>> opening("foo") as f: >>> # etc. >> >>I'm still -1 for the same reason I mentioned earlier: function calls >>spanning multiple lines are moderately common in Python code, and it's >>hard to distinguish these cases because multi-line calls usually get >>indented like blocks. > > But the indentation of a multi-line call doesn't start with a colon. Neither does the un-keyworded block. It starts with a colon on the end of the previous line. I thought part of the point of Python was to minimize reliance on punctuation, especially where it's not clearly visible? Actually, I've just realized that I was misled by your argument into thinking that the possibility of confusing a multi-line call and a block of this sort is a problem. It's not, because template blocks can be viewed as multi-line calls that just happen to include a block of code as one of the arguments. So, mistaking one for the other when you're just skimming the code and not looking at things like "as" or the ":", is really not important. In the second place, the most important cue to understanding the behavior of a template block is the template function itself; the bare syntax gives it the most prominence. Blocks like 'synchronized(self):' should be instantly comprehensible to Java programmers, for example, and 'retry(3):' is also pretty self-explanatory. And so far, template function names and signatures have been quite brief as well. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
On Fri, Apr 29, 2005, Phillip J. Eby wrote: > > Actually, I've just realized that I was misled by your argument into > thinking that the possibility of confusing a multi-line call and a block of > this sort is a problem. It's not, because template blocks can be viewed as > multi-line calls that just happen to include a block of code as one of the > arguments. So, mistaking one for the other when you're just skimming the > code and not looking at things like "as" or the ":", is really not > important. Maybe. I'm not persuaded, but this inclines me toward agreeing with your position. > In the second place, the most important cue to understanding the behavior > of a template block is the template function itself; the bare syntax gives > it the most prominence. Blocks like 'synchronized(self):' should be > instantly comprehensible to Java programmers, for example, and 'retry(3):' > is also pretty self-explanatory. And so far, template function names and > signatures have been quite brief as well. This works IMO IFF Python is regarded as a language with user-defined syntactical structures. Guido has historically disagreed strongly with that philosophy; until and unless he reverses his opinion, this is precisely why the non-keyword version will continue to receive -1 from me. (As it happens, I agree with Guido, so if Guido wants to change, I'll probably argue until I see good reason. ;-) -- Aahz ([EMAIL PROTECTED]) <*> http://www.pythoncraft.com/ "It's 106 miles to Chicago. We have a full tank of gas, a half-pack of cigarettes, it's dark, and we're wearing sunglasses." "Hit it." ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] Re: PEP 340 - possible new name for block-statement
Guido van Rossum wrote: >> Another possibility just occurred to me. How about "using"? > > Blah. I'm beginning to like block just fine. With using, the choice of > word for the generator name becomes iffy IMO; and it almost sounds > like it's a simple renaming: "using X as Y" could mean "Y = X". FWIW, the first association when seeing block something: is with the verb "to block", and not with the noun, which is most displeasing. Reinhold -- Mail address is perfectly valid! ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
[Phillip] > > In the second place, the most important cue to understanding the behavior > > of a template block is the template function itself; the bare syntax gives > > it the most prominence. Blocks like 'synchronized(self):' should be > > instantly comprehensible to Java programmers, for example, and 'retry(3):' > > is also pretty self-explanatory. And so far, template function names and > > signatures have been quite brief as well. [Aahz] > This works IMO IFF Python is regarded as a language with user-defined > syntactical structures. Guido has historically disagreed strongly with > that philosophy; until and unless he reverses his opinion, this is > precisely why the non-keyword version will continue to receive -1 from > me. (As it happens, I agree with Guido, so if Guido wants to change, > I'll probably argue until I see good reason. ;-) Actually, I think this is a nice way to have my cake and eat it too: on the one hand, there still isn't any user-defined syntax, because the keyword-less block syntax is still fixed by the compiler. On the other hand, people are free to *think* of it as introducing syntax if it helps them understand the code better. Just as you can think of each distinct @decorator as a separate piece of syntax that modifies a function/method definition. And just as you can think of a function call as a user-defined language extension. -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
On 4/29/05, Guido van Rossum <[EMAIL PROTECTED]> wrote: > [Phillip J. Eby] > > Although I'd personally prefer a no-keyword approach: > > > > synchronized(self): > > with_file("foo") as f: > > # etc. > > I'd like that too, but it was shot down at least once. Maybe we can > resurrect it? > > opening("foo") as f: > # etc. > > is just a beauty! > Yes. I like it. EXPRESSION [as VAR]: BLOCK lock(self._monitor): # typing synchronized freaks me out spam() using(DB.open()) as conn: eggs(conn) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340: syntax suggestion - try opening(filename) as f:
[Michael Spencer] > I don't know whether it's true for all the PEP 340 use cases, but the all the > current examples would read very naturally if the block-template could be > specified in an extended try statement: Sorry, this emphasizes the wrong thing. A try-statement emphasizes that the body may fail (and then provides some cleanup semantics). IMO a block-statement, while it has cleanup semantics, should emphasize that the block executes under some kind of supervision. The more I think about it the more I like having no keyword at all (see other messages). -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Anonymous blocks: Thunks or iterators?
On 29 apr 2005, at 20.10, Brian Sabbey wrote: [...] The thunk and its surrounding function can share the same code. The thunk gets compiled into the function the same way the body of a for loop would. This seems really, truly, nasty! Wouldn't this require you to check the source code of the function you want to integrate your thunk into to avoid namespace collisions? Well, no, not to avoid collisions I guess, if it's truly regarded as part of the function. But this means it would use the function's global namespace, etc. You'd be unable to use anything from the scopes in which the thunk is defined, which makes it really, really ... wierd. Or have I not gotten it? //Simon ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
Pierre Barbier de Reuille wrote: Mmmmh ... why introduce a new flag ? Can't you just test the presence of the "__error__" method ? This would lift your problem wouldn't it ? Perhaps - it would require doing something a little tricky with generators to allow the programmer to specify whether the generator should be finalised or not. Cheers, Nick. -- Nick Coghlan | [EMAIL PROTECTED] | Brisbane, Australia --- http://boredomandlaziness.skystorm.net ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
Guido van Rossum wrote: [Phillip J. Eby] Although I'd personally prefer a no-keyword approach: synchronized(self): with_file("foo") as f: # etc. I'd like that too, but it was shot down at least once. Maybe we can resurrect it? opening("foo") as f: # etc. is just a beauty! +1 Certainly my favorite because it's direct and easy on the eyes. Second would be:: in opening("foo") as f: # etc. because I can see Aahz's point about introducing the block with a keyword instead of relying on the ":" punctuation and subsequent indentation of the block for skimming code. -Shane Holloway ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340: syntax suggestion - try opening(filename) as f:
On Fri, 29 Apr 2005, Guido van Rossum wrote: > The more I think about it the more I like having no keyword at all > (see other messages). I hope you'll reconsider this. I really think introducing a new statement requires a keyword, for pedagogical reasons as well as readability and consistency. Here's my pitch: All the statements in Python are associated with keywords, except for assignment, which is simple and extremely common. I don't think the block statement is simple enough or common enough for that; its semantics are much too significant to be flagged only by a little punctuation mark like a colon. I can empathize with wanting to avoid a keyword in order to avoid an endless debate about what the keyword will be. But that debate can't be avoided anyway -- we still have to agree on what to call this thing when talking about it and teaching it. The keyword gives us a name, a conceptual tag from which to hang our knowledge and discussions. Once we have a keyword, there can be no confusion about what to call the construct. And if there is a distinctive keyword, a Python programmer who comes across this unfamiliar construct will be able to ask someone "What does this 'spam' keyword mean?" or can search on Google for "Python spam" to find out what it means. Without a keyword, they're out of luck. Names are power. -- ?!ng ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340 - possible new name for block-statement
At 04:02 PM 4/29/05 -0700, Guido van Rossum wrote: Actually, I think this is a nice way to have my cake and eat it too: on the one hand, there still isn't any user-defined syntax, because the keyword-less block syntax is still fixed by the compiler. On the other hand, people are free to *think* of it as introducing syntax if it helps them understand the code better. Just as you can think of each distinct @decorator as a separate piece of syntax that modifies a function/method definition. And just as you can think of a function call as a user-defined language extension. And, amusingly enough, those folks who wanted a decorator suite can now have their wish, e.g.: decorate(classmethod): def something(cls, blah): ... Given a suitable frame-sniffing implementation of 'decorate'. :) By the way, I notice PEP 340 has two outstanding items with my name on them; let me see if I can help eliminate one real quick. Tracebacks: it occurs to me that I may have unintentionally given the impression that I need to pass in an arbitrary traceback, when in fact I only need to pass in the current sys.exc_info(). So, if the error call-in doesn't pass in anything but an error flag, and the template iterator is supposed to just read sys.exc_info(), maybe that would be less of an issue? For one thing, it would make handling arbitrary errors in the template block cleaner, because the traceback for unhandled errors in something like this: synchronized(foo): raise Bar would look something like this: File line ... of __main__: synchronized(foo): File line ... of synchronized: yield File line ... of __main__: raise Bar Which, IMO, is the "correct" traceback for this circumstance, although since the first and last frame would actually be the same, you'd probably only get the lower two entries (the yield and the raise), which is OK too I think. Anyway, I mainly just wanted to note that I'd be fine with having a way to say, "Hey, there's an error, handle it" that doesn't allow passing in the exception or traceback, but is just a flag that means "look at Python's error state" instead of passing a value back in. I can do this because when I need to pass in a traceback, it's because I'm trying to pass a terminated coroutine's error into another coroutine. So, the traceback I want to pass in is Python's existing "last error" state anyway. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 340: syntax suggestion - try opening(filename) as f:
At 08:21 PM 4/29/05 -0500, Ka-Ping Yee wrote: All the statements in Python are associated with keywords, except for assignment, which is simple and extremely common. I don't think the block statement is simple enough or common enough for that; its semantics are much too significant to be flagged only by a little punctuation mark like a colon. Don't forget the 'as' clause. I can empathize with wanting to avoid a keyword in order to avoid an endless debate about what the keyword will be. But that debate can't be avoided anyway -- we still have to agree on what to call this thing when talking about it and teaching it. A "template invocation", perhaps, for the statement, and a "templated block" for the actual block. The expression part of the statement would be the "template expression" which must result in a "template iterator". The keyword gives us a name, a conceptual tag from which to hang our knowledge and discussions. Once we have a keyword, there can be no confusion about what to call the construct. And if there is a distinctive keyword, a Python programmer who comes across this unfamiliar construct will be able to ask someone "What does this 'spam' keyword mean?" or can search on Google for "Python spam" to find out what it means. Without a keyword, they're out of luck. Names are power. help(synchronized) or help(retry) would doubtless display useful information. Conversely, try Googling for Python's "for" or "if" keywords, and see if you get anything useful -- I didn't. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com