The problem with "as" [was "Re: PEP 318"]

David MacQuigg dmq at gain.com
Fri Mar 26 11:48:17 EST 2004


>>>[Stephen Horne]:
>>>What I might use is something like...
>>>
>>>  pragma printoptions ( separator = ' ', terminator = '\n' ) :
>>>    print "whatever"
>>>    print "something else"
>>>
>>>...as a general way of providing standard-behaviour-overriding flags
>>>for built-ins.
>>
>>[David MacQuigg]:
>>I like this.  It keeps the basic syntax of the print statement clean.
>>It avoids a lot of typing in situations where there is a repetition of
>>the same 'decoration' on many statemtents.  The main drawback I see is
>>that in many situations, the modifcation is 'one time only'.  Then we
>>have *three* statements instead of one. ( We need a statement to
>>restore the default printoptions.)

>[Stephen Horne]:
>No, we need two statements. There is no need to restore the default
>printoptions - only to dedent out of the block where the non-default
>printoptions are set. The implementation would have printoptions in a
>stack structure, so the most recent override can always be easily
>referenced.
>
>The two-line format for isolated prints needing non-default options
>isn't too bad as it would be a struggle to keep such print statements
>on one line in practical cases anyway.
>
>The biggest problem would be the case where there are prints dotted
>throughout the code which all use the same nondefault options. And
>even then, you could probably use something like...
>
>  pragma printoptions ( separator = ' ', terminator = '\n' ) :
>    main_program_call ()

[David MacQuigg]:
This last example takes care of the case where *every* print statement
needs the same options.  I think what is more likely is having only
*some* print statements that need, for example, to be redirected to a
special file.  Those statements are not likely to be neatly grouped,
so we will have to set a 'pragma' block on each one.

There may also be some objection to the fact that this use of
indentation (setting options) is inconsistent with every other use
(controlling program flow).

>>Using the "common-symbol-for-a statement-extension" syntax, we could
>>modify multiple statements without too much clutter using something
>>like:
>>
>>opts = printoptions( separator = ' ', terminator = '\n' )
>>print @(opts) "whatever"
>>print @(opts) "something else"
>
>OK - this certainly has advantages. But it assumes that the only way
>to extend a print statement would be to accept some kind of attributes
>from a specified object.
>
>If you're really doing named extensions, that should be...
>
>  opts = printoptions( separator = ' ', terminator = '\n' )
>  print @(printoptions: opts) "whatever"
>
>Otherwise, your standard extensions symbol isn't standard - it is used
>to do different things in different contexts, as its use to apply
>decorators in def is fundamentally different to its use to apply
>printoptions in print.

The common concept is "syntax extension".  This could be options in a
print statement ( print @opts ... ), decorators in a function def (
def f(x,y) @decs : ... ) or modifying the meaning of a return
statement in a generator ( @return ).  With options and decorators we
have some additional commonality.  In both these contexts, the @
symbol says "Look next for an object, or a tuple of objects meaningful
to this particular statement."  In both cases we define that object
ourselves, and give it a name meaningful in our particular program.

squeeze = printoptions( separator = None )
noLF    = printoptions( terminator = None )
print @squeeze x, y, z
...
print @noLF x, y, z

If either of these print statements is a "one-time-only", we could
stick the printoptions directly after the @ symbol.  The token
following the @ symbol in a print statement is either a 'printoptions'
object, or just the keyword parameters used to construct such an
object.  This dual syntax is used, for example in functions which can
accept a filename or a file object.

>Alternately, instead of allowing your symbol to handle any new
>extension syntax, it could just handle one syntax - applying
>nonstandard options. In this case, the decorators example might become
>something like...
>
>  def name (args) @{ "decorators" : [deco1, deco2, deco3]} :
>    pass
>
>Or, for convenience...
>
>  opts = { "decorators" : [deco1, deco2, deco3]}
>
>  def name (args) @opts :
>    pass
>
>Actually, I quite like this. I suspect that pretty much any extension
>to a statement could be handled using a set of named options stored in
>a dictionary.

It's even broader than that.  Dictionaries or other special objects
could be associated with @ in certain statements.  In others, like
using @ to introduce a nameless function, no special objects are
needed.  We need not even put @ at the beginning of a keyword or
object to be modified.  What if instead of 'yield' we used 'return@',
meaning "This is a normal return, except that execution will resume on
the next call, right here after the return."  I'm not saying this has
any advantage over @return, just illustrating the flexibility in not
assigning any unecessary meaning or syntax to @.

>I'm still scratching my head a little, but at least now I know that I
>was confused ;-)

Aren't we all.  It is fun, however, discussing ideas about the perfect
language.  This is the best time to do it, while we are learning the
language. Later, we will forget the problems we had in learning.  I've
already forgotten the hassle with 'self', but it is interesting to do
a Google search on "group:comp.lang.python insubject:self"  1080 hits
!!  This is a problem which won't go away.  Also one that could have
been solved with a special symbol, but if you want to get into that
discussion, I'll have to post under a different name. :>)

-- Dave




More information about the Python-list mailing list