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