pre-PEP: Suite-Based Keywords
Bengt Richter
bokr at oz.net
Tue Apr 19 00:50:24 EDT 2005
On Mon, 18 Apr 2005 12:50:24 +0200, Reinhold Birkenfeld <reinhold-birkenfeld-nospam at wolke7.net> wrote:
>Bengt Richter wrote:
>> On Sun, 17 Apr 2005 15:25:04 +0200, Reinhold Birkenfeld <reinhold-birkenfeld-nospam at wolke7.net> wrote:
>
>>>> Note that there is no problem adding other parameters, because ::<suite> is just
>>>> a unary expression returning dict subtype instance, e.g.,
>>>>
>>>> y = f(11,22,**::
>>>> x = 1
>>>> y = 'y for f'
>>>> )*g(*args_from_somewhere, **::
>>>> x = 'x for g'
>>>> y = 'y for g'
>>>> def foo(): return 'foo for g'
>>>> )
>>>
>>>You know that this is dead ugly?
>> What aspect in particular?
>
>The '**::', for example. I would surely prefer a keyword instead of '::'.
I thought it was concise and mnemonic, in that ':' already introduces suites, and '::'
introduces exactly the same thing, only processing it differently, which is suggested
concisely by '::' being different from ':' ;-)
>
>> I.e., does this (currently legal) look prettier:
>>
>> y = f(11,22, **dict(
>> x = 1,
>> y = 'y for f'
>> ))*g(*args_from_somewhere, **dict(
>> x = 'x for g',
>> y = 'y for g',
>> foo = lambda: return 'foo for g'
>> ))
>
>No, it doesn't. And I surely wouldn't write such code.
>
>y = (f(11, 22, x=1, y='y for f') *
> g(*args_from_somewhere, x='x for g', y='y for g', foo=lambda: return 'foo for g'))
>
>or, if you tolerate more lines,
>
>y = (f(11, 22, x=1, y='y for f') *
> g(*args_from_somewhere,
> x='x for g', y='y for g',
> foo=lambda: return 'foo for g'))
>
>would be my current way to express this. But still, the less lines,
>the less confusing it is.
>
Chacun a son gout ;-)
>> Can you express the same semantics in a prettier way?
>>
>> To boil it down, doesn't a suite bindings expression like
>>
>> d = ::
>> x = 1
>> y = 'y for f'
>>
>> (which in this case doesn't even need parens) seem prettier than
>>
>> d = dict(
>> x = 1,
>> y = 'y for f'
>> )
>>
>> to you, especially given that (:: ...) gives you the power
>> of full suite syntax to create bindings
>> any way you want[1], not just keyword=<expression> ?
>> (and you can leave out the commas ;-)
>
>I understand the general idea, but still I don't like the idea of "suite expressions".
>My main concern is the following: After a suite expression, where does code
>follow?
>
>As in your example:
>
>y = f(**::
> x = 1 # indented one level, as indents can go any number of spaces
> ) # indented one level too, but differently (currently an IndentantionError)
I don't understand your example. Think of it as a triple quoted string, except that it opens
with :: and doesn't require \ to ignore the first blank line, and it closes with dedent or
a closing bracket that was not opened in the "string".
That closing paren doesn't belong to the :: suite (having been opened outside the suite).
Therefore, no matter where it appears, it will end the suite, and play its own role in
matching its partner (right after f here).
If you parenthesize you are fully free to indent your first line anywhere, e.g. (perversely)
y = f(**(:: # note paren
x = 1
) # blank line with 7 spaces ends the suite
# you can't get left of the reference indentation here, so it's
# good that ')' ends the suite ;-)
) # closes f( -- legal at any indentation, since we're inside an open bracket
If you don't parenthesize, your suite will end where a normal if x: suite would end by dedent
Note that
if x:
z=2
is a syntax error, and you would expect the same with
x = ::
z = 2
if :: required something on the next line, but unlike an if with no inline suite, :: doesn't require it,
and just sees that z is at or left of the existing indentation of x, so the z is a dedent ending a blank suite,
and z better line up with something, as in
if x:
x = :: # blank suite
z = 2
So you can write
d1 = ::
x = 1
d2 = :: x=2
d2 = ::
def foo(): pass
and expect what you'd expect if you were me ;-)
BTW, surrounding brackets such as f(...) do not do away with the indentation rules
_within a_ :: suite, they just let you start it where you want.
>
>> [1] I.e., this should work to extend the power of the type expression in a way
>> that shows what you can't do with dict(...) ;-)
>>
>> type('C', (), ::
>> def __repr__(self):
>> return '<alternatively-created-class-object at %08x>'% (hex(id(self)&(2L**32-1))
>> def cname(self): return type(self).__name__
>> classvar = 123
>> # ... anything you can do in a class definition body
>> )
>>
>> IMO that's pretty clean.
>
>Uses are neat, i concur.
Maybe I can win you over ;-)
>
>>>The real ``problem'' (if you see one) is that the indentation syntax
>>>doesn't allow for suites in expressions.
>>
>> I was trying to solve that "problem" with my "suite expressions" ;-)
>>
>> ::<suite> # suite bindings expression (as ordered dict)
>> def(<arglist>):<suite> # anonymous def
>> (<arglist>):<suite> # thunk (anonymous callable suite sharing local namespace)
>>
>> I think suite indentation rules for suite expressions are not that hard, once you decide
>> to deal with it as a separate indentation space from outside the expression. That's already
>> done to allow multiline expressions without indentation interpretation inside bracketed expressions.
>> This is just adding indentation processing within certain types of expressions ("suite expressions" ;-)
>>
>> For the most part I like indentation syntax very well, and
>> I suspect that if there were optional brackets, you would still be indenting
>> for clarity, so the chances are the bracket version of the above would
>> mainly add bracket noise to something close to the above.
>
>I don't say brackets are better, but the problem of where to put the following code
>is tricky.
Why is it more tricky than the suite of if x: ?
And when can't you easily resolve a doubt with explicit parens?
Regards,
Bengt Richter
More information about the Python-list
mailing list