RE: [Python-Dev] Anonymous blocks: Thunks or iterators?

2005-04-29 Thread Robert Brewer
 [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

2005-04-29 Thread Josiah Carlson

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] Anonymous blocks: Thunks or iterators?

2005-04-29 Thread Michael Hudson
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 yieldn.
 :-)

Hmm, it's nearly *May* 1... :)

Cheers,
mwh

-- 
  I'm a keen cyclist and I stop at red lights.  Those who don't 

Re: [Python-Dev] Anonymous blocks: Thunks or iterators?

2005-04-29 Thread Michael Hudson
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

2005-04-29 Thread Pierre Barbier de Reuille
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

2005-04-29 Thread Paul Moore
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

2005-04-29 Thread Luis P Caamano
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
python-dev@python.org
 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

2005-04-29 Thread Luis Bruno
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

2005-04-29 Thread Shane Hathaway
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

2005-04-29 Thread Jim Jewett
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

2005-04-29 Thread Luis P Caamano
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?

2005-04-29 Thread Skip Montanaro

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?

2005-04-29 Thread Skip Montanaro

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

2005-04-29 Thread Nick Coghlan
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

2005-04-29 Thread Nick Coghlan
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

2005-04-29 Thread Pierre Barbier de Reuille
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?

2005-04-29 Thread Aahz
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

2005-04-29 Thread Aahz
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

2005-04-29 Thread David Ascher
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

wink/
___
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

2005-04-29 Thread Josiah Carlson

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

2005-04-29 Thread Josiah Carlson

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


[Python-Dev] Anonymous blocks: Thunks or iterators?

2005-04-29 Thread Jim Jewett
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

2005-04-29 Thread David Ascher
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

2005-04-29 Thread David Ascher
 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

2005-04-29 Thread Aahz
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?

2005-04-29 Thread Jim Jewett
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] Anonymous blocks: Thunks or iterators?

2005-04-29 Thread Guido van Rossum
[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

2005-04-29 Thread Ron Adam
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:
   block
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] Anonymous blocks: Thunks or iterators?

2005-04-29 Thread Brian Sabbey
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:

2005-04-29 Thread 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).
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?

2005-04-29 Thread Jim Jewett
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

2005-04-29 Thread John J Lee
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] Anonymous blocks: Thunks or iterators?

2005-04-29 Thread Jim Jewett
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:

2005-04-29 Thread Jim Jewett
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

2005-04-29 Thread Aahz
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

2005-04-29 Thread André Roberge
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

2005-04-29 Thread Nicolas Fleury
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

2005-04-29 Thread Phillip J. Eby
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

2005-04-29 Thread Aahz
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


Re: [Python-Dev] PEP 340 - possible new name for block-statement

2005-04-29 Thread Rodrigo B. de Oliveira
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] Anonymous blocks: Thunks or iterators?

2005-04-29 Thread Simon Percivall
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

2005-04-29 Thread Nick Coghlan
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

2005-04-29 Thread Shane Holloway (IEEE)
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:

2005-04-29 Thread Ka-Ping Yee
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

2005-04-29 Thread Phillip J. Eby
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:

2005-04-29 Thread Phillip J. Eby
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