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