Statement local namespaces summary (was Re: python3: 'where' keyword)
Nick Coghlan
ncoghlan at iinet.net.au
Fri Jan 14 02:15:02 EST 2005
Bengt Richter wrote:
> Problems? (Besides NIH, which I struggle with regularly, and had to overcome to accept Tim's
> starting point in this ;-)
The ideas regarding creating blocks whose name bindings affect a different scope
are certainly interesting (and relevant to the 'using' out-of-order execution
syntax as well).
Out-of-order execution appeals to me, but the ability to flag 'hey, this is just
setup for something I'm doing later' might be a reasonable alternative
(particularly with the affected names highlighted on the first line). As Jeff
pointed out, it would be significantly less surprising for those encountering
the construct for the first time. Folding code editors would be able to keep the
setup clause out of the way if you really wanted to hide it.
On the other hand, it might be feasible to construct a virtually identical
out-of-order two suite syntax, similar to the mathematical phrasing "let f =
c/lambda where f is the frequency, c is the speed of light and lambda is the
wavelength". Either way, you've convinced me that two suites (and a new compound
statement), as well as specifying which names can be rebound in the containing
scope, is a better way to go than trying to mess with the definition of Python
statements.
On keywords, while 'let' is nice for assignments, I find it just doesn't parse
properly when I put function or class definitions in the clause. So, I'll swap
it for 'use' in the examples below. The statement could then be read "use these
outer bindable names, and this additional code, in this suite". YMMV, naturally.
Let's consider some of the examples given for 'where' using an in-order let/in
type syntax (the examples only bind one name at a time, but would allow multiple
names):
# Anonymous functions
use res:
def f(x):
d = {}
exec x in d
return d
in:
res = [f(i) for i in executable]
# Declaring properties
class C(object):
use x:
def get(self):
print "Demo default"
def set(self, value):
print "Demo default set"
in:
x = property(get, set)
# Design by contract
use foo:
def pre():
pass
def post():
pass
in:
@dbc(pre, post)
def foo():
pass
# Singleton classes
use C:
class _C:
pass
in:
C = _C()
# Complex default values
use f:
def default():
return "Demo default"
in:
def f(x=default()):
pass
They actually read better than I expected. Nicely, the semantics of this form of
the syntax *can* be articulated cleanly with current Python:
use <names>: <use-suite>
in: <in-suite>
as equivalent to:
def __use_stmt():
<use-suite>
def _in_clause():
<in-suite>
return <names>
return _in_clause()
__use_stmt_args = {}
<names> = __use_stmt()
del __use_stmt
Those semantics don't allow your switch statement example, though, since it
doesn't use any magic to write to the outer scope - it's just a normal return
and assign.
However, I don't think starting with these semantics would *preclude* adding the
ability to name the second block at a later date, and make the name rebinding
part of executing that block - the standard usage doesn't really care *how* the
names in the outer scope get bound, just so long as they do. Whether I think
that's a good idea or not is an entirely different question :)
Another aspect to consider is whether augmented assignment operations in the
inner-scopes should work normally - if so, it would be possible to alter the
semantics to include passing the existing values as arguments to the inner scopes.
Moving on to considering a two-suite out-of-order syntax, this would have
identical semantics to the above, but a syntax that might look something like:
as <names>: <in-suite>
using: <use-suite>
# Anonymous functions
as res:
res = [f(i) for i in executable]
using:
def f(x):
d = {}
exec x in d
return d
# Declaring properties
class C(object):
as x:
x = property(get, set)
using:
def get(self):
print "Demo default"
def set(self, value):
print "Demo default set"
# Design by contract
as foo:
@dbc(pre, post)
def foo():
pass
using:
def pre():
pass
def post():
pass
# Singleton classes
as C:
C = _C()
using:
class _C:
pass
# Complex default values
as f:
def f(x=default()):
pass
using:
def default():
return "Demo default"
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at email.com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
More information about the Python-list
mailing list