On 16 Apr 2005 09:07:09 -0700, "Kay Schluehr" <[EMAIL PROTECTED]> wrote:
>The idea is interesting but not unambigously realizable. Maybe one
>should introduce some extra syntax for disambiguation and thereby
>generalize the proposal.
This is intriguing. I am reminded of trailing "where x is something" phrase,
but with
an implied x.
>
>as <specifier>:
> # list of definitions and assignments
ISTM this list, other than for func, always could be considered to
generate an ordered sequence of (key, value) pairs that need to be plugged into
the preceding context. Where to plug it in is implicit, but it could be given
explicit target name(s) in an expression, e.g.,
<expr> where: <where-suite>
and <where-suite> would be a series of assignments like for suite-based
keywords, except that
the key names would be used in resolving the names in the expression preceding
the where:, e.g.,
foo(x, y) where:
x = 1
y = 2
would make the foo call using the where bindings by name, here effectively
calling foo(1, 2)
But sometimes we want all the bindings in a suite in a chunk, as with
suite-based keyword bindings.
I'm proposing below a unary suite operator spelled '::' which will return a
single tuple of 2-tuples
representing the ordered bindings produced by the statement suite following the
'::' Thus ::<suite>
is a general expression that can be used anywhere an expression can be used.
(I'll explain indentation rules).
The "::" expression I'm proposing generalizes capturing suite bindings into an
ordered sequence of (key,value)
tuples, like an ordered vars().items() limited to the bindings produced in the
suite following "::"
Thus
items = ::
x = 1
y = [1,2]
def foo():pass
print items => (('x', 1), ('y', [1, 2]), ('foo', <function foo at
0x02EE8D14>))
Now we can use a :: expression in a where: spec, e.g.
d = dict(items) where:
items = ('added','value') + :: # note that :: is a unary suite
operator producing a tuple of tuples
x = 1
y = [1,2]
def foo():pass
where: actually introduces a suite of scoped assignments much like :: e.g.,
d = {key:value} where: key='x'; value='123' # where is ;-greedy on the same
line
print d => {'x':123}
or a multi-parameter call
foo(x, y=23, *args, **kw) where:
x = 333; y = 555
args = [44, 55, 66]
kw = dict(::
z = 'zee'
class C(object): pass
c = C()
del C )
resulting in foo being called like foo(333, 555, 44, 55, 66, z='zee', c=C()) #
except C was transiently defined
You can also use a :: expression directly, skipping the where: reference
resolution mechanism, e.g.,
d = dict(::
x = 1
y = [1,2]
def foo():pass) # closing bracket not opened in :: suite ends the
suite like a sufficient dedent would
It can also participate as a normal expression anywhere a tuple of tuples could
go, e.g.
print list(t[0] for t in ::
x = 1
y = [1,2]
def foo():pass)
=> ['x', 'y', 'foo']
Now we can rewrite some examples. Thanks for the inspiration to
generalize/orthogonalize ;-)
>
>Proposed specifiers are dict, tuple, *, ** and func.
>
>
>- as dict:
>
> conversion into a dictionary
>
> Example:
>
> d = as dict:
> doc = "I'm the 'x' property."
> def fget(self):
> return self.__x
d = dict(items) where:
items = ::
doc = "I'm the 'x' property."
def fget(self):
return self.__x
Or more concisely
d = dict(::
doc = "I'm the 'x' property."
def fget(self):
return self.__x )
>
> We would get d = {"doc":"I'm the 'x' property.", "fget":fget}
>
>
>- as **:
>
> conversion into keyword-arguments. This comes close in spirit to the
> original proposal
BTW, this would happen to cover dict alternatively by way of your format
d = dict():
as **: key=value #etc
>
> Example:
>
> x = property():
> as **:
> doc = "I'm the 'x' property."
> def fget(self):
> return self.__x
>
x = property(**kw) where:
kw = dict(::
doc = "I'm the 'x' property."
def fget(self):
return self.__x)
or
x = property(fget=fget, doc=doc) where:
doc = "I'm the 'x' property."
def fget(self):
return self.__x
>- as tuple:
>
> conversion into a tuple. Preserving order.
>
> Example:
>
> t = as tuple:
> doc = "I'm the 'x' property."
> def fget(self):
> return self.__x
> >>> t[1]
> <function fget at 0x00EC4770>
"as tuple:" is special sugar for
t = tuple(*v) where:
v = (t[1] for t in ::
doc = "I'm the 'x' property."
def fget(self):
return self.__x )
>
>
>- as *:
>
> conversion into an argument tuple. Preserving order.
That's the same as passing values to tuple above
>
> Example:
>
> x = property():
> as *:
> def get_x():
> return self.__x
> def set_x(value):
> self.__x = value
> del_x = None
> doc = "I'm the 'x' property."
x = property(*seq) where:
seq = (item[1] for item in ::
def get_x():
return self.__x
def set_x(value):
self.__x = value
del_x = None
doc = "I'm the 'x' property." )
>
>
>
>- as func(*args,**kw):
>
> Anoymus functions. Replacement for lambda. Support for
> arbirtray statements?
I prefer dropping combinations of def and/or <name> from def
<name>(<arglist>): <suite>
to get
def <name>(<arglist>): <suite> # normal def
def (<arglist>): <suite> # anonymous def
<name>(<arglist>): <suite> # named callable suite, aka named thunk
(<arglist>): <suite> # anonymous callable suite, aka thunk
any of which can be passed to a decorator or bound or passed to functions
etc.
The parsing of indentation for the three last definitions is like for the
:: unary suite operator
i.e., they are all expressions, not statements, and ::<suite> is an
expression that ends where the
<suite> ends, so there are some rules. The first is that a closing bracket
not opened within the suite
ends the suite. This is typically the closing paren of a function call, but
could be anything, e.g.,
print [:: x=123; y=456] => [(('x', 123), ('y', 456))] # ie the :: value is
a single tuple of tuples.
More typical would be the use of def(<arglist>):<suite> as a substitute for
lambda <arglist>:<expr>
BTW, note that :: is ;-greedy in a single-line multi-statement suite, so
items = :: x=1; y=2 # => (('x',1), ('y',2))
I.e., it has the effect of
items = ::
x = 1
y = 2
Not
items == ::
x = 1
y = 2
The same greediness goes for "where:"
>
> Examples:
>
> p = as func(x,y): x+y
> p(1,2)
p = def(x, y): x+y
>
> i,j = 3,4
> if (as func(x,y): x+y) (i,j) > 10:
> print True
if (def(x,y): x+y) (i,j) > 10:
print true
I haven't thought of all the uses for anonymous callable suites (thunks), but
imagine as callback:
(putting it as an unusual default parameter makes it bind in the same namspace
as the definintion of foo)
def foo(x, cb=(y):print y):
cb(x)
foo(3) # => prints 3 and assigns y=3 as local-to-foo-definer side effect
(often main effect)
foo(123, (z):print 'Setting z=%r'%z) => prints Setting z=123 and sets z=123
locally to foo caller.
foo(456, lambda *ignore:None) # also legal, foo doesn't know what callable
it's being passed
The suite-based keyword call syntax
foo():
x = 1
y = [1,2]
def foo():pass
can be handled with the more general
foo(**kw) where: kw = dict(::
x = 1
y = [1,2]
def foo():pass)
This is a new rev on my thoughts. Expect contradictions with older stuff.
Naturally I like my newest ideas best ;-)
Regards,
Bengt Richter
--
http://mail.python.org/mailman/listinfo/python-list