pre-PEP: Suite-Based Keywords - syntax proposal

Bengt Richter bokr at oz.net
Tue Apr 19 06:35:47 EDT 2005


On 19 Apr 2005 00:16:32 -0700, "Kay Schluehr" <kay.schluehr at gmx.net> wrote:

>
>Bengt Richter wrote:
>
>[...]
>
>> Um, I think that's too narrow for where. Consider
>>
>>     foo = f1; bar=f2; x=k1; y=k2
>>     foo(x)*bar(y)[3].attr
>>
>> now should
>>
>>     foo(x)*bar(y)[3].attr where:
>>         foo = f1; bar=f2; x=k1; y=k2
>
>I think we are diverging again. You are right with Your objection about
>my claim of generality but I'm completely against the latter statement
>not only because
>
>foo(x) where:
>   foo = f1
>
>is not much better than
>
>foo(x) where:
>   def foo():
>       # do some stuff
>
>which should clearly raise an exception and be abandoned.

Why do you say that? foo(x) is just a call of whatever foo is bound to.
The where: suite supplies a transient namespace where foo happens to
be defined in the conventional way. This allows definition and call of
foo without binding it in the caller's local namespace, much like
    (lambda(): do_some_stuff)()

IMO that's a perfectly valid use. You don't have to worry that your
def foo():... will clobber some other foo.

>
>After all I start backtracking: the purpose of defining suites is still
>prevention of namespaces pollution with helper-functions not a sake of
>it's own and not inventing of a suite-based programming style for
>everything. The examples You presented have become almost pathological
>examples of what should be prevented and where syntax cannot be rigid
>enough.
You don't have to write what you consider to be pathological, but
this becomes sort of a free speech issue. I.e., don't impose a style-censoring
spell-checker on me please ;-)

>
>So there are following requierements about we seem to agree:
>
>- define suites on a functions-call scope in order to define helper
>functions
>  that would otherwise pollute external namespaces
Why just function call? You realize that a "function call" is just the
effect of (<arglist>) tacked on the tail of an expression that is not
necessarily just a name. E.g., notice the possibilities the parser goes
through before finding that foo() is a simple name expression with a () trailer:

[ 1:18] C:\pywk\parse\ast>py24 debg.py -full foo()
'file_input'
  'stmt'
    'simple_stmt'
      'small_stmt'
        'expr_stmt'
          'testlist'
            'test'
              'and_test'
                'not_test'
                  'comparison'
                    'expr'
                      'xor_expr'
                        'and_expr'
                          'shift_expr'
                            'arith_expr'
                              'term'
                                'factor'
                                  'power'
                                    'atom'
                                      NAME 'foo'
                                    'trailer'
                                      LPAR '('
                                      RPAR ')'
      NEWLINE ''
  ENDMARKER ''

What about instance.method(args) as a call? Should you not be
able  write
           instance.method(*args) where:
              args = []
              # append various values to args here,
              # in single statements and/or using looping etc.

to specify complex args in a where? That looks like

[ 2:18] C:\pywk\parse\ast>py24 debg.py -full instance.method(*args)
'file_input'
  'stmt'
    'simple_stmt'
      'small_stmt'
        'expr_stmt'
          'testlist'
            'test'
              'and_test'
                'not_test'
                  'comparison'
                    'expr'
                      'xor_expr'
                        'and_expr'
                          'shift_expr'
                            'arith_expr'
                              'term'
                                'factor'
                                  'power'
                                    'atom'
                                      NAME 'instance'
                                    'trailer'
                                      DOT '.'
                                      NAME 'method'
                                    'trailer'
                                      LPAR '('
                                      'arglist'
                                        STAR '*'
                                        'test'
                                          'and_test'
                                            'not_test'
                                              'comparison'
                                                'expr'
                                                  'xor_expr'
                                                    'and_expr'
                                                      'shift_expr'
                                                        'arith_expr'
                                                          'term'
                                                            'factor'
                                                              'power'
                                                                'atom'
                                                                  NAME 'args'
                                      RPAR ')'
      NEWLINE ''
  ENDMARKER ''

What about other expressions that can retrieve a callable whose arguments you might want to compute
with logic? My bet is that neither of us can predict what pain an arbitrary restriction on natural
consequences of a good orthogonal grammar change will do. In another post I did sketch out a grammar
mod that prevents a whole bunch of nonsense such as continue where ... (and I'm not sure I caught all
true silliness), but I would rather not restrict for pure style reasons. Obviously the BDFL went the
style-restrictive way with decorator expressions, since functionally any expression after the '@'
which returned a callable taking a function as its first argument could have been allowed.
I agree (after some mixed feelings ;-) about that in the decorator case, but I think where-functionality
is much more general.


>
>- mark the func-call-scope by some keyword either "with" or "where"
>because
>  it has to be separated from the calling environment both for
>consistency
>  and user friendlyness
Not sure what you mean by func-call scope, but I assume you are referring to
what is created by processing the where suite.

The way I have been thinking of this for where is to translate

     <tiny_stmt> where <wheresuite>

to
     def uniquetmp(): # return dict with bindings created in wheresuite
        <where-suite>
        return vars()
     
     exec_with_shadowing_name_space( uniquetmp(), <tiny_stmt> )

IOW, the idea is to execute the tiny_stmt normally, except that any names accessed
will first be looked up in the dict returned by uniquetmp(), and if not found there
will go on to the normal local space of tiny_stmt and then to its globals.

Thunks are tricky, because while bound in the where suite namespace, their code bodies
share the namespace outside of the where scope.

I think I can implement the functionality with a combination of import-time AST rewriting
and byte code hacks, but I am not sure I want to expend the energy doing that. Better to
expend it getting set up to do real experimental changes. But I need to upgrade a bunch
of stuff to do that ;-/

>
>- Simple matching rules for both keyword-parameters and
>argument-tuples.
This almost suggests source-level macro processing to me, which is _NOT_ what
where is about. "Matching" in my view is not textual, it happens dynamically at run time
and names not supplied will cause run time name errors, not syntax errors.

>  Make explicit which kind of inference rule is selected.
I'm not sure what this means ;-)

>
>I think that my last proposal I finally distilled from our discussion
>would pretty much fullfill all three requirements whereas that of
>Andrey Tatarinov would be somewhat more restrictive and fullfills only
>the first two. 
Maybe you could summarize it as a concrete grammar change? That would help
make it clear. I enjoy this ping pong, but it takes up a lot of time ;-)

Regards,
Bengt Richter



More information about the Python-list mailing list