Re: [Python-Dev] PEP 340: Breaking out.

2005-05-06 Thread Paul Moore
On 5/5/05, Steven Bethard [EMAIL PROTECTED] wrote:
 On 5/5/05, Paul Moore [EMAIL PROTECTED] wrote:
  And does your proposal allow for continue EXPR as supported by PEP
  340? I can't see that it could, given that your proposal treats block
  statements as not being loops.
 
 Read PEP 340 again -- the continue EXPR syntax is orthogonal to the
 discussion -- PEP 340 adds it for *all* for loops, so for loops with
 the non-looping block statements would also be able to use it.

I know this. But we're talking here about Nick's new proposal for a
non-looping block. All I am saying is that the new proposal needs to
include this orthogonal feature. If it's a modification to PEP 340,
that will come naturally. If it's a modification to PEP 310, it won't.
A new PEP needs to include it.

I am very much against picking bits out of a number of PEPs - that was
implicit in my earlier post - sorry, I should have made it explicit.
Specifically, PEP 340 should be accepted (possibly with modifications)
as a whole, or rejected outright - no rejected, but can we have
continue EXPR in any case, as it's orthogonal status exists...

  The looping behaviour is a (fairly nasty) wart, but I'm not sure I
  would insist on removing it at the cost of damaging other features I
  like.
 
 I don't think it damages any features.  Are there features you still
 think the non-looping proposal removes?  (I'm not counting orthogonal
 feautres like continue EXPR which could easily be added as an
 entirely separate PEP.)

I *am* specifically referring to these orthogonal features. Removal
of looping by modification of PEP 340 will do no such damage, I
agree - but removal by accepting an updated PEP 310, or a new PEP,
*will* (unless the entirely separate PEP you mention is written and
accepted along with the non-looping PEP - and I don't think that will
happen).

Thanks for making me clarify what I meant. I left a little too much
implicit in my previous post.

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] PEP 340: Breaking out.

2005-05-06 Thread Paul Moore
On 5/6/05, Greg Ewing [EMAIL PROTECTED] wrote:
 Seems to me it should be up to the block iterator whether
 a break statement gets caught or propagated, since it's
 up to the block iterator whether the construct behaves
 like a loop or not.
 
 This could be achieved by having a separate exception
 for breaks, as originally proposed.
 
 If the iterator propagates the Break exception back out,
 the block statement should break any enclosing loop.
 If the iterator wants to behave like a loop, it can
 catch the Break exception and raise StopIteration
 instead.

Yes, that's exactly what I was trying to say! I don't know if it's
achievable in practice, but the fact that it was in the original
proposal (something I'd forgotten, if indeed I ever realised) makes it
seem more likely to me.

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] PEP 340: Breaking out.

2005-05-06 Thread Nicolas Fleury
Guido van Rossum wrote:
Maybe generators are not the way to go, but could be
supported natively by providing a __block__ function, very similarly to
sequences providing an __iter__ function for for-loops?
 
 Sorry, I have no idea what you are proposing here.

I was suggesting that the feature could be a PEP310-like object and that 
a __block__ function (or whatever) of the generator could return such an 
object.  But at this point, Nick's proposition is what I prefer.  I find 
the use of generators very elegant, but I'm still unconvinced it is a 
good idea to use them to implement an acquire/release pattern.  Even if 
another continuation mechanism would be used (like Steven's idea), it 
would still be a lot of concepts used to implement acquire/release.

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: Breaking out.

2005-05-05 Thread Ka-Ping Yee
On Thu, 5 May 2005, Delaney, Timothy C (Timothy) wrote:
 Aahz wrote:
  My standard workaround is using exceptions, but I'm not sure how that
  interacts with a block:
 
  try:
  for name in filenames:
  with opened(name) as f:
  if f.read(2) == 0xFEB0:
  raise Found
  except Found:
  pass

 For any sane block iterator, it will work as expected. However, an evil
 block iterator could suppress the `Found` exception.

I was thinking about more use cases for the block statement,
and one of the ideas was an exception-logging block:

def logged_exceptions(file):
try:
yield
except Exception, value:
file.write(repr(value) + '\n')

block logged_exceptions(file):
do stuff
do stuff
do stuff

...but then i wasn't sure whether this was supposed to be
possible in the proposed scheme.  Currently, generators do not
catch exceptions raised in the code that they yield values to,
because the target of the yield is in a higher stack frame.

This makes sense from a language design perspective, since
there is no try...finally construct lexically wrapping the thing
that raises the exception.  In current Python, for example,
this says 'caught outside generator':

def spam_generator():
try:
yield 'spam'
except ValueError, value:
print 'caught inside generator'

try:
g = spam_generator()
i = g.next()
raise ValueError(5)
except ValueError, value:
print 'caught outside generator'

But now i'm confused.  Tim's words above seem to suggest that
the interior generator could actually catch exceptions raised
outside, by whatever is on the other end of the yield.

So, could a block statement really catch that exception inside?
I think it might be too confusing if it were possible.


-- ?!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: Breaking out.

2005-05-05 Thread Nick Coghlan
Steven Bethard wrote:
 Makes me wonder if we shouldn't just return to the __enter__() and
 __exit__() names of PEP 310[1] where for a generator __enter__() is
 just an alias for next().  We could even require Phillip J. Eby's
 blockgenerator decorator to rename next() to __enter__(), and add
 the appropriate __exit__() method.

You must be reading my mind or something. . .

Unless there is something in today's 80-odd messages to make it redundant, look 
for a post entitled something like Minimalist PEP 340 (aka PEP 310 redux)

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: Breaking out.

2005-05-05 Thread Nick Coghlan
Alex Martelli wrote:
 Looking for a file with a certain magicnumber in its 1st two bytes...?
 
 for name in filenames:
  opening(name) as f:
  if f.read(2) == 0xFEB0: break
 
 This does seem to make real-life sense to me...

Also consider the vast semantic differences between:

   locking(lock):
   for item in items:
   if can_handle(item): break

   for item in items:
   locking(lock):
   if can_handle(item): break


Instead of simply acquiring and releasing the lock on each iteration as one 
might expect, moving to the latter version *also* causes every item to be 
checked, instead of only items up to the first one that can be handled. The 
break magically becomes meaningless. How does this even come close to 
executable 
pseudocode?

I also think another factor is that currently, instead of doing try/finally's 
in 
loops, there is a tendency to push the try/finally into a function, then call 
that function inside the loop. The introduction of block statements means that 
a 
number of those inner functions are likely to be handled as block statements 
instead - with the above highly confusing result.

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: Breaking out.

2005-05-05 Thread Eric Nieuwland
Ronald Oussoren wrote:
 What's bothering me about the proposed semantics is that block
 statement behaves like a loop while most use cases do no looping 
 whatsoever.
 Furthermore the it doesn't feel like loop either. In all three 
 examples on this page I'd assume
 that the break would break out of the for loop.

I'm bothered the same way.
IMHO control constructs should be very clear. No implicit looping, 
conditionals etc.
Especially since the main reason to have this whole discussion is about 
resource management.
The main pattern of use I have in mind is:

resource = grab/allocate/open/whatever(...)
try:
do something possibly with the resource
except ...:
...
finally:
...
resource.release/deallocate/close/whatever()

This is linear. No looping whatsoever. And easily translated to a 
simple language construct and a protocol:

class resource(object):
def __init__(self,...):
# store resource parameters
def __acquire__(self):
# whatever it takes to grab the resource
def __release__(self):
# free the resource

res = resource(...)
acquire res:
do something possibly with the resource
except ...:
...
finally:
...

The resource is automagically released at the end of the 'acquire' 
block (keyword up for other proposals :-)
An alternative syntax could also be allowed:

acquire resource(...) as res:
...etc...

Then 'res' would be undefined after the 'acquire' block.

--eric

___
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: Breaking out.

2005-05-05 Thread Steven Bethard
On 5/5/05, Nick Coghlan [EMAIL PROTECTED] wrote:
 Steven Bethard wrote:
  Makes me wonder if we shouldn't just return to the __enter__() and
  __exit__() names of PEP 310[1] where for a generator __enter__() is
  just an alias for next().  We could even require Phillip J. Eby's
  blockgenerator decorator to rename next() to __enter__(), and add
  the appropriate __exit__() method.
 
 You must be reading my mind or something. . .
 
 Unless there is something in today's 80-odd messages to make it redundant, 
 look
 for a post entitled something like Minimalist PEP 340 (aka PEP 310 redux)

Yeah, I should have linked to that discussion [1].  I wonder if it
would be possible to update PEP 310 with your ideas, or perhaps start
a new PEP?  I'd like to see a competitor for PEP 340 that addresses
some of the issues that came up, e.g. that the block-statement doesn't
look like a loop, so break and continue might look like they break out
of an enclosing loop.  It might also be a good place to mirror Guido's
PEP 340 examples with PEP 310-style examples -- I know the first
attempts at writing some of them weren't as clean as the later
attempts, so it would be nice to have somewhere to look for the
current version of everything.

STeVe

[1]http://mail.python.org/pipermail/python-dev/2005-April/053039.html
-- 
You can wordify anything if you just verb it.
--- Bucky Katt, Get Fuzzy
___
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: Breaking out.

2005-05-05 Thread Josiah Carlson

Ka-Ping Yee [EMAIL PROTECTED] wrote:
 
 On Thu, 5 May 2005, Josiah Carlson wrote:
  Ka-Ping Yee [EMAIL PROTECTED] wrote:
   continue with 2
 
  There is something about action which level that I just don't like.
 
 Just to clarify: if by level you mean nesting level, did it appear
 that the 2 in my example was a count of block levels?  I didn't
 mean it that way -- the 2 is a value passed in to the generator
 that appears as the value of the yield expression, as in PEP 340.

I remember reading that, but I seem to have forgotten it when I was
composing my reply.  Thankfully, sleeping on it has helped me discover
what I really don't like.  With the 'passing value' semantic, the
action [ which ] [ value ] is only useful for the deepest loop of
a particular type. Take for example...

for ...:
for ...:
for ...:
break/continue [for]


That break or continue can only affect that last for loop.  It doesn't
make any easier the use of nested fors, nested whiles, or even nested
blocks.  It only really helps you if you mix and match all possible
looping constructs, and even then, only gives the granularity of the
most recent block of a particular type.  In that sense, I think it is a
nonstarter, because it doesn't really add functionality in common uses
of for and while statements.

If one allowed action [which] [value] , [level], then one could
jump to arbitrary loops.  Now, I'm not condoning this, and I don't even
like it.  Sure, it allows breaking or continuing to any for, while, or
block statement in the current scope, but the level argument is as
equivalently ambiguous as package-relative imports using a leading
integer (http://python.org/peps/pep-0328.html).

Now, one can remove ambiguity if we were able to 'label' while loops and
for loops producing action [ label ] , [ value ], but at that
point we are getting into the discussion of a loop-aware goto with
loop/block cleanup, and a syntax for labeling loops.  Ick.

 - 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: Breaking out.

2005-05-05 Thread Paul Moore
On 5/5/05, Nick Coghlan [EMAIL PROTECTED] wrote:
 Well, Michael Hudson and Paul Moore are the current authors of PEP 310, so
 updating it with any of my ideas would be their call.

I'm willing to consider an update - I don't know Michael's view. I
currently find myself in the odd situation of defending PEP 340
against PEP 310, though. I'll try to rationalise why below...

 Either way, my latest and greatest version of the non-looping block statement
 semantics can be found here:
 http://mail.python.org/pipermail/python-dev/2005-May/053400.html

I can't reconcile this description with that of PEP 310. The basic
reason is that the styles are very different, compounded by the fact
that I don't have the time to give this the analysis it needs.

My instinct is that if your proposal can't be described in terms of a
relatively small change to one of PEP 310 or 340, then my view is it's
a 3rd proposal in its own right, and I'd rather not open things up
that much again.

 Some key advantages of that proposal are:
1. It's not a loop, so nesting it inside another loop 'just works'

This, to me, is the main issue

2. Manual protocol implementations are _significantly_ easier to write

Hmm, I've not tried so I'll have to take your word for this. But I
don't imagine writing manual implementations much - one of the key
features I like about Guido's proposal is that generators can be used,
and the implementation is a clear template, with yield acting as a
put the block here marker (yes, I know that's an
oversimplification!).

3. try/finally can be done with generators _without_ changing generators

How is this an advantage? PEP 340 allows try/finally inside generators
- if that counts as changing generators I don't see why I care (as a
user). But I think I'm missing something here - I never really
followed (or cared about) the generator finalisation issues.

4. try/except/else can be done with generators if they provide an __exit__
 method that raises the exception at the point of the last yield

As above - I'm not sure I follow.

5. Clearly distinct construct, no potential for confusion with for loops

OK, but that's really just saying not a loop again.

6. Generators must be clearly marked as creating a user defined statement
 (although this could be changed by giving them an __enter__ method and an
 __exit__ method)

I still don't see a compelling argument that this is a good thing. I'm
neutral on this.

 The one downside relative to PEP 340 is that looping constructs like 
 auto_retry
 are slightly harder to write, albeit not hugely so (once you remember that an
 iterable can be a class instead of a generator!).

Are you *sure* that's the only downside? Early on in the PEP 340
discussion, generator finalisation was a point of discussion. I didn't
follow the details, but I believe that one of the points of PEP 340
was that it addressed the issues (to some extent - I really don't know
if the generator finalisation PEPs are rendered obsolete by PEP 340,
are completely orthogonal, or somewhere in between). I have no feel
for whether your proposal covers these issues in the same way as PEP
340 does.

And does your proposal allow for continue EXPR as supported by PEP
340? I can't see that it could, given that your proposal treats block
statements as not being loops. Having just noticed this, I start to
feel less convinced that block-as-loop is ultimately wrong. There
aren't any examples of continue EXPR included in PEP 340 yet - a fact
that Guido has acknowledged in item 9 of the examples section. Maybe
Philip or one of the other coroutine fans would like to contribute
some examples?

 On the usage front, I find the
 'loop over an iterator returning user defined statements' does a much better 
 job
 of making the iteration clear, so I'd be inclined to count that as an 
 advantage
 of a PEP 310 style approach.

I can accept that. It's a minor style point either way. The wording of
it - as returning user defined statements makes me nervous though,
as it implies that user-defined statements are first class objects -
which feels wrong.

 Anyway, I've already been spending more time on this than I should (sleep is
 optional, right?), so I won't be prettying it up into PEP format any time 
 soon.
 I have no objection to someone else rolling some of the ideas into a PEP, 
 though :)

I think *someone* has to care enough (and have the time) to make a
proper PEP out of this. If it's a minor change to either of PEP 310 or
PEP 340, that's OK. If it's too big for that, it needs to be fleshed
out as a full competing PEP in its own right.

Oh - and the promised rationalisation of my preference for PEP 340
over PEP 310. Things I like about PEP 340:

  - Using generators as templates with yield as a put the block
here placeholder. It may be that a modification of PEP 310 can
provide this, but that PEP doesn't exist yet (sorry!)
  - The coroutine style continue EXPR feature (I still need
motivating examples but as a 

Re: [Python-Dev] PEP 340: Breaking out.

2005-05-05 Thread Steven Bethard
On 5/5/05, Paul Moore [EMAIL PROTECTED] wrote:
 And does your proposal allow for continue EXPR as supported by PEP
 340? I can't see that it could, given that your proposal treats block
 statements as not being loops.

Read PEP 340 again -- the continue EXPR syntax is orthogonal to the
discussion -- PEP 340 adds it for *all* for loops, so for loops with
the non-looping block statements would also be able to use it.

 The looping behaviour is a (fairly nasty) wart, but I'm not sure I
 would insist on removing it at the cost of damaging other features I
 like.

I don't think it damages any features.  Are there features you still
think the non-looping proposal removes?  (I'm not counting orthogonal
feautres like continue EXPR which could easily be added as an
entirely separate PEP.)

STeVe
-- 
You can wordify anything if you just verb it.
--- Bucky Katt, Get Fuzzy
___
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: Breaking out.

2005-05-05 Thread Greg Ewing
Seems to me it should be up to the block iterator whether
a break statement gets caught or propagated, since it's
up to the block iterator whether the construct behaves
like a loop or not.

This could be achieved by having a separate exception
for breaks, as originally proposed.

If the iterator propagates the Break exception back out,
the block statement should break any enclosing loop.
If the iterator wants to behave like a loop, it can
catch the Break exception and raise StopIteration
instead.

-- 
Greg Ewing, Computer Science Dept, +--+
University of Canterbury,  | A citizen of NewZealandCorp, a   |
Christchurch, New Zealand  | wholly-owned subsidiary of USA Inc.  |
[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] PEP 340: Breaking out.

2005-05-05 Thread Greg Ewing
Simon Percivall wrote:

 And this is not confusing in what way?

I don't think it's any less confusing than having a
construct in the first place which can either be a
loop or not. You need to know the semantics of the
block iterator in order to know whether it's a loop.
Once you know that, you know how break behaves (as
long as the iterator is sanely designed).


  Making it depend
 means you constantly have to readjust your understanding
 of the statement based on the context. And this is _if_
 you know how it behaves in the particular case. If you're
 trying to understand the source code, having break depend
 on something defined somewhere completely else seems like
 an obstacle to easy understanding. IMHO, of course.
 
 //Simon
 


-- 
Greg Ewing, Computer Science Dept, +--+
University of Canterbury,  | A citizen of NewZealandCorp, a   |
Christchurch, New Zealand  | wholly-owned subsidiary of USA Inc.  |
[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] PEP 340: Breaking out.

2005-05-05 Thread Greg Ewing
Delaney, Timothy C (Timothy) wrote:

 In this scenario (and I'm not saying I approve or disapprove) I think
 BreakIteration should inherit from StopIteration (thus retaining the
 existing PEP 340 semantics if uncaught)::

Not sure I understand. The point of my suggestion was
to *not* retain existing PEP 340 semantics if uncaught,
i.e. break an enclosing loop rather than just terminate
the block statement.

-- 
Greg Ewing, Computer Science Dept, +--+
University of Canterbury,  | A citizen of NewZealandCorp, a   |
Christchurch, New Zealand  | wholly-owned subsidiary of USA Inc.  |
[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] PEP 340: Breaking out.

2005-05-04 Thread Nick Coghlan
Paul Moore wrote:
 Oh, and by the way - I prefer the keywordless form of the block
 statement (as used in my examples above). But it may exacerbate the
 issue with break unless we have a really strong name for these
 constructs

may exacerbate? Something of an understatement, unfortunately. 'break' and 
'continue' are going to be useless in most block statements, and in most of the 
cases where that is true, one would expect them to break out of a surrounding 
loop.

Reconsidering the non-looping semantics I discussed way back at the start of 
this exercise, this is what using auto_retry would look like with a single-pass 
block statement:

   for attempt in auto_retry(3, IOError):
   attempt:
   # Do something!
   # Including break and continue to get on with the next attempt!

(Now that's what I call a user defined statement - we're iterating over a list 
of them!)

Anyway, auto_retry and the block statements it returns could be implemented as:

   def suppressing(exc=Exception, on_success=None):
   Suppresses the specified exception in the following block
   try:
   yield
   except exc:
   pass
   else:
   if on_success is not None:
on_success()

   def just_do_it():
   Simply executes the following block
   yield

   def auto_retry(times, exc=Exception):
   Generates the specified number of attempts
   class cb():
   succeeded = False
   def __init__(self):
   cb.succeeded = True

   for i in xrange(times-1):
   yield suppressing(exc, cb)
   if cb.succeeded:
   break
   else:
   yield just_do_it()


(Prettier than my last attempt at writing this, but still not very pretty. 
However, I'm willing to trade the need for that callback in the implementation 
of auto_retry to get non-surprising behaviour from break and continue, as the 
latter is visible to the majority of users, but the former is not)

Note that the code above works, even *if* the block statement is a looping 
construct, making a mess out of TOOWTDI.

Making it single pass also simplifies the semantics of the block statement 
(using VAR1 and EXPR1 from PEP 340):

 finalised = False
 block_itr = EXPR1
 try:
 try:
 VAR1 = block_itr.next()
 except StopIteration:
 # Can still choose not to run the block at all
 finalised = True
 except:
 # There was an exception. Handle it or just reraise it.
 finalised = True
 exc = sys.exc_info()
 ext = getattr(block_itr, __exit__, None)
 if ext is not None:
 ext(*exc)   # May re-raise *exc
 else:
 raise *exc   # Well, the moral equivalent :-)
 finally:
 if not finalised:
 # The block finished cleanly, or exited via
 # break, return or continue. Clean up the iterator.
 ext = getattr(block_itr, __exit__, None)
 if ext is not None:
 try:
 ext(StopIteration)
 except StopIteration:
 pass


With single-pass semantics, an iterator used in a block statement would have 
it's .next() method called exactly once, and it's __exit__ method called 
exactly 
once if the call to .next() does not raise StopIteration. And there's no need 
to 
mess with the meaning of break, return or continue - they behave as usual, 
affecting the surrounding scope rather than the block statement.

The only new thing needed is an __exit__ method on generators (and the block 
syntax itself, of course).

Looks like I've come full circle, and am back to arguing for semantics closer 
to 
those in PEP 310. But I have a better reason now :)

 Actually,
 maybe referring to them as block statements, but using no keyword,
 is perfectly acceptable. As I write, I'm finding it more and more
 natural.

Same here. Especially if the semantics are tweaked so that it *is* a 
straightforward statement instead of a loop.

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: Breaking out.

2005-05-04 Thread Alex Martelli

On May 4, 2005, at 01:57, Paul Moore wrote:

 tried to construct a plausible example, I couldn't find a case which
 made real-life sense. For example, with Nicolas' original example:

 for name in filenames:
 opening(name) as f:
 if condition: break

 I can't think of a reasonable condition which wouldn't involve reading
 the file - which either involves an inner loop (and we already can't
 break out of two loops, so the third one implied by the opening block
 makes things no worse), or needs the whole file reading (which can be

Looking for a file with a certain magicnumber in its 1st two bytes...?

for name in filenames:
 opening(name) as f:
 if f.read(2) == 0xFEB0: break

This does seem to make real-life sense to me...


Alex

___
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: Breaking out.

2005-05-04 Thread Paul Moore
On 5/4/05, Alex Martelli [EMAIL PROTECTED] wrote:
 
 On May 4, 2005, at 01:57, Paul Moore wrote:
 
  I can't think of a reasonable condition which wouldn't involve reading
  the file - which either involves an inner loop (and we already can't
  break out of two loops, so the third one implied by the opening block
  makes things no worse), or needs the whole file reading (which can be
 
 Looking for a file with a certain magicnumber in its 1st two bytes...?
 
 for name in filenames:
 opening(name) as f:
 if f.read(2) == 0xFEB0: break
 
 This does seem to make real-life sense to me...

Yes, that'd do. I can't say I think it would be common, but it's a
valid case. And the workaround is the usual messy flag variable:

for name in filenames:
found = False
opening(name) as f:
if f.read(2) == 0xFEB0: found = True
if found: break

Yuk.

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] PEP 340: Breaking out.

2005-05-04 Thread Steven Bethard
On 5/4/05, Nick Coghlan [EMAIL PROTECTED] wrote:
 With single-pass semantics, an iterator used in a block statement would have
 it's .next() method called exactly once, and it's __exit__ method called 
 exactly
 once if the call to .next() does not raise StopIteration. And there's no need 
 to
 mess with the meaning of break, return or continue - they behave as usual,
 affecting the surrounding scope rather than the block statement.
 
 The only new thing needed is an __exit__ method on generators (and the block
 syntax itself, of course).

Makes me wonder if we shouldn't just return to the __enter__() and
__exit__() names of PEP 310[1] where for a generator __enter__() is
just an alias for next().  We could even require Phillip J. Eby's
blockgenerator decorator to rename next() to __enter__(), and add
the appropriate __exit__() method.  Something like:

class blockgen(object):
def __init__(self, gen):
self.gen = gen
def __enter__(self):
self.gen.next()
def __exit__(self):
# cause finally blocks to be executed

def blockgenerator(genfunc):
def getblockgen(*args, **kwargs):
return blockgen(genfunc(*args, **kwargs))
return getblockgen

to be used like:

@blockgenerator
def locking(lock):
lock.acquire()
try:
yield
finally:
lock.release()

'Course, it might be even nicer if try/finally around a yield could
only be used with block generators...  To get a syntax error, we'd
have to replace the decorator with a new syntax, e.g. Tim Delaney's
resource instead of def syntax or maybe using something like
blockyield or resourceyield instead of yield (though these are
probably too long)...

Steve

[1]http://www.python.org/peps/pep-0310.html
-- 
You can wordify anything if you just verb it.
--- Bucky Katt, Get Fuzzy
___
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: Breaking out.

2005-05-04 Thread Reinhold Birkenfeld
Paul Moore wrote:
 On 5/4/05, Alex Martelli [EMAIL PROTECTED] wrote:
 
 On May 4, 2005, at 01:57, Paul Moore wrote:
 
  I can't think of a reasonable condition which wouldn't involve reading
  the file - which either involves an inner loop (and we already can't
  break out of two loops, so the third one implied by the opening block
  makes things no worse), or needs the whole file reading (which can be
 
 Looking for a file with a certain magicnumber in its 1st two bytes...?
 
 for name in filenames:
 opening(name) as f:
 if f.read(2) == 0xFEB0: break
 
 This does seem to make real-life sense to me...
 
 Yes, that'd do. I can't say I think it would be common, but it's a
 valid case. And the workaround is the usual messy flag variable:
 
 for name in filenames:
 found = False
 opening(name) as f:
 if f.read(2) == 0xFEB0: found = True
 if found: break

Is there anything we could do about this?

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: Breaking out.

2005-05-04 Thread Shane Hathaway
Alex Martelli wrote:
 Looking for a file with a certain magicnumber in its 1st two bytes...?
 
 for name in filenames:
  opening(name) as f:
  if f.read(2) == 0xFEB0: break
 
 This does seem to make real-life sense to me...

I'd like to suggest a small language enhancement that would fix this
example.  Allow the break and continue statements to use a keyword,
either for or while, to state that the code should break out of both
the block statement and the innermost for or while statement.  The
example above would change to:

for name in filenames:
opening(name) as f:
if f.read(2) == 0xFEB0:
break for

This could be a separate PEP if necessary.  When a break for is used
in a block statement, it should raise a new kind of exception,
BreakForLoop, and the block statement should propagate the exception.
When used outside a block statement, break for can use existing Python
byte code to jump directly to the next appropriate statement.

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


Re: [Python-Dev] PEP 340: Breaking out.

2005-05-04 Thread Ka-Ping Yee
On Wed, 4 May 2005, Shane Hathaway wrote:
 I'd like to suggest a small language enhancement that would fix this
 example.  Allow the break and continue statements to use a keyword,
 either for or while, to state that the code should break out of both
 the block statement and the innermost for or while statement.  The
 example above would change to:

 for name in filenames:
 opening(name) as f:
 if f.read(2) == 0xFEB0:
 break for

This is very elegant.  It works beautifully with break, though at
first that natural analogs continue for, continue while appear to
conflict with Guido's proposed extension to continue.

But if we choose the keyword with to introduce an anonymous block,
it comes out rather nicely:

continue with 2

That's easier to read than continue 2, in my opinion.  (If it's not
too cute for you.)

Anyway, i like the general idea of letting the programmer specify
exactly which block to break/continue, instead of leaving it looking
ambiguous.  Explicit is better than implicit, right?


-- ?!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: Breaking out.

2005-05-04 Thread Shane Hathaway
Ka-Ping Yee wrote:
 On Wed, 4 May 2005, Shane Hathaway wrote:

for name in filenames:
opening(name) as f:
if f.read(2) == 0xFEB0:
break for
 
 
 This is very elegant.

Thanks.

  It works beautifully with break, though at
 first that natural analogs continue for, continue while appear to
 conflict with Guido's proposed extension to continue.
 
 But if we choose the keyword with to introduce an anonymous block,
 it comes out rather nicely:
 
 continue with 2
 
 That's easier to read than continue 2, in my opinion.  (If it's not
 too cute for you.)

Or perhaps:

continue yield 2

This would create some symmetry, since generators will retrieve the
value passed by a continue statement using a yield expression.

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


Re: [Python-Dev] PEP 340: Breaking out.

2005-05-03 Thread Pierre Barbier de Reuille

Tom Rothamel a écrit :
 I have a question/suggestion about PEP 340.
 
 As I read the PEP right now, the code:
 
 
 while True:
 
 block synchronized(v1):
  if v1.field:
   break
 
 time.sleep(1)
 
 
 Will never break out of the enclosing while loop. This is because the
 break breaks the while loop that the block statement is translated
 into, instead of breaking the outer True statement. 

Well, that's exactly what it is intended to do and what I would expect 
it to do ! break/continue affect only the inner-most loop.

 
 Am I understanding this right, or am I misunderstanding this?
 
 If I am understanding this right, I would suggest allowing some way of
 having the iterator call continue or break in the enclosing
 context. (Perhaps by enclosing the entire translation of block in a
 try-except construct, which catches Stop and Continue exceptions
 raised by the generator and re-raises them in the outer context.)
 
 I hope this helps.
 

I don't want it like that ! This would differ with the break/continue 
used in other loops. If you need to break from many loops, enclose them 
into a function and return from it !

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] PEP 340: Breaking out.

2005-05-03 Thread Skip Montanaro
 Pierre == Pierre Barbier de Reuille [EMAIL PROTECTED] writes:

Pierre Tom Rothamel a écrit :
 I have a question/suggestion about PEP 340.
 
 As I read the PEP right now, the code:
 
 while True:
 block synchronized(v1):
 if v1.field:
 break
 time.sleep(1)
 
 Will never break out of the enclosing while loop.

Pierre Well, that's exactly what it is intended to do and what I would
Pierre expect it to do ! break/continue affect only the inner-most
Pierre loop.

Yeah, but block synchronized(v1) doesn't look like a loop.  I think this
might be a common stumbling block for people using this construct.

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: Breaking out.

2005-05-03 Thread Pierre Barbier de Reuille


Skip Montanaro a écrit :
 [...]
 
 Yeah, but block synchronized(v1) doesn't look like a loop.  I think this
 might be a common stumbling block for people using this construct.
 
 Skip
 

Well, this can be a problem, because indeed the black-statement 
introduce a new loop construct in Python. That's why I advocated some 
time ago against the introduction of a new name. IMHO, the for-loop 
syntax can be really used instead of blocks as its behavior if exactly 
the one of a for-loop if the iterator is an iterator-for-for and the 
current for-loop cannot be used with iterator-for-blocks.

The main problem with this syntax is the use of the blocks for things 
that are not loops (like the synchronize object)! And they are, indeed, 
quite common ! (or they will be :) ).

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] PEP 340: Breaking out.

2005-05-03 Thread Guido van Rossum
[Skip Montanaro]
 Yeah, but block synchronized(v1) doesn't look like a loop.  I think this
 might be a common stumbling block for people using this construct.

How many try/finally statements have you written inside a loop? In my
experience this is extrmely rare. I found no occurrences in the
standard library.

-- 
--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: Breaking out.

2005-05-03 Thread Guido van Rossum
[Skip Montanaro]
  Yeah, but block synchronized(v1) doesn't look like a loop.  I think
  this might be a common stumbling block for people using this
  construct.
 
 Guido How many try/finally statements have you written inside a loop?
 Guido In my experience this is extrmely rare. I found no
 Guido occurrences in the standard library.

[Skip again]
 How'd we start talking about try/finally?

Because it provides by far the dominant use case for 'block'. The
block-statement is intended to replace many boilerplace uses of
try/finally. In addition, it's also a coroutine invocation primitive.

 To the casual observer, this
 looks like break should break out of the loop:
 
 while True:
 block synchronized(v1):
 ...
 if v1.field:
 break
 time.sleep(1)

Without 'block' this would be written as try/finally. And my point is
that people just don't write try/finally inside a while loop very
often (I found *no* examples in the entire standard library).

 The PEP says:
 
 Note that it is left in the middle whether a block-statement
 represents a loop or not; this is up to the iterator, but in the
 most common case BLOCK1 is executed exactly once.
 
 That suggests to me it's still not clear if the block statement is actually
 a looping statement.  If not, then break should almost certainly break out
 of the while loop.

Dynamically, it's most likely not a loop. But the compiler doesn't
know that, so the compiler considers it a loop.

 BTW, what did you mean by left in the middle mean?  I interpreted it as
 still undecided, but it's an idiom I've never seen.  Perhaps it should be
 replaced by something more clear.

It may be a Dutch phrase that doesn't translate to English as wel as I
thought. It doesn't exactly mean still undecided but more depends
on your POV. I'll use something different, and also clarify that as
far as break/continue are concerned, it *is* a loop.

-- 
--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: Breaking out.

2005-05-03 Thread Nicolas Fleury
Guido van Rossum wrote:
 [Skip Montanaro]
Guido How many try/finally statements have you written inside a loop?
Guido In my experience this is extrmely rare. I found no
Guido occurrences in the standard library.
 
How'd we start talking about try/finally?
 
 Because it provides by far the dominant use case for 'block'. The
 block-statement is intended to replace many boilerplace uses of
 try/finally. In addition, it's also a coroutine invocation primitive.

I would expect programmers to do more than only replace existing 
try/finally blocks.  The support for RAII patterns in Python might 
result in more use of RAII primitives and some may fit very well inside 
a loop.  It might not be a bad idea to look at what other languages are 
doing with RAII.  Also, even if there's no occurence right now in the 
standard library, it doesn't mean it has always been the case in the 
code evolution, where debugging such pitfall would not be cool.

FWIW, I expect most generators used in block-syntax to not be loops. 
What would imply to support these to pass break to parent loop at 
run-time?  Maybe generators are not the way to go, but could be 
supported natively by providing a __block__ function, very similarly to 
sequences providing an __iter__ function for for-loops?

We could avoid explaining to a newbie why the following code doesn't 
work if opening could be implemented in way that it works.

for filename in filenames:
 block opening(filename) as file:
 if someReason: break

By the way, FWIW, my preference if to have no keyword, making it clearer 
that some block statements are loops and others not, but probably 
amplifying the break problem.

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