remaining decorator syntax options
Bengt Richter
bokr at oz.net
Tue Aug 10 20:12:44 EDT 2004
On 10 Aug 2004 12:33:36 -0700, steven.bethard at gmail.com (Steven Bethard) wrote:
>So here's the state of the decorator debate as I see it:
>
>
>*** Location
>
>GvR pretty strongly wants decorators before the function:
>
>http://mail.python.org/pipermail/python-dev/2004-August/047112.html
>http://mail.python.org/pipermail/python-dev/2004-August/047279.html
>
>The idea being that decorators and other function properties should
>not look like part of the function's code. I don't think there's much
>chance of swaying GvR on this count.
>
>
>*** Indentation
>
>Since location has been pretty much decided, I see three options here:
>
>(1)
><indicator> dec
>def f():
> pass
>
>(2)
><indicator>
> dec
>def f():
> pass
>
>(3)
><indicator> dec
> def f():
> pass
>
(4)
dec<indicator>
def f():
pass
Suggested indicator: '(=' or '(:' or '(%' e.g.,
dec(=
def f():
pass
>GvR definitely disliked the third version because it meant that class
>functions could all be at different indentation levels. The PEP
>suggests that the second version was disliked because it suggests that
>"using" is introducing a new scope (although arguments about if/else
>behavior seemed to counter this somewhat). There didn't seem to be
>any arguments that made version 2 drastically better than version 1
>though, so it seems most likely that a BDFL pronouncement will give us
>version 1.
>
>
>*** List notation
>
>Assuming a pre-def, non-indented decorator, here are the remaining
>list notations:
>
>(1)
><indicator> dec1
><indicator> dec2
><indicator> dec3
>
>(2)
><indicator> [dec1, dec2, dec3]
>
>(3)
><indicator> dec1, dec2, dec3
>
(4)
dec1<indicator>
dec2<indicator>
dec3<indicator>
e.g.,
dec1(=
dec2(=
dec3(=
def f(): pass
>I believe that version 3 was vetoed because it makes it too hard to
>break lists of decorators across lines. GvR's preference is
>definitely for 1, but that may be influenced by his decision for the
>indicator. I have a feeling that how long the indicator is directly
>affects which of (1) or (2) is preferred. Compare:
>
>@dec1
>@dec2
>@dec3
>
>vs.
>
>@[dec1, dec2, dec3]
>
>and
>
>using dec1
>using dec2
>using dec3
>
>vs.
>
>using [dec1, dec2, dec3]
>
>It seems like with a single symbol character, the non-list syntax is
>much more concise, and probably clearer. However with a keyword
>syntax the list seems the better option.
>
>Which brings us, of course to the final section:
>
>*** Indicator
>
>The options seemed to be:
>
>(1) a symbol (@, |, etc.)
>(2) a keyword (using, decorate, etc.)
>(3) similar to function
>(4) no indicator
>
(5) postfixed indicators [ (: (= (% <<< etc ]
dec1 (=
dec2 (=
def foo(): pass
>Options (3) and (4) were ruled out because (given that we're already
>relegated to a before-def syntax) they are already valid syntax, and
>redefining them for decorators means changing the expected semantics
>of the statements.
>
>Option (1), with @, is GvR's favorite, and does have something of a
>Java backing. It has the substantial disadvantage that there is no
>particular reason (or even some sort of mnemonic) for which @ (or |
>for that matter) should mean "decorator".
>
>With option (2), we can choose a keyword that does suggest a
>decorator. Even "using", which is not an outstanding choice, is at
>least more intuitive than '@'. Option (2) does have the disadvantage
>that it requires introducing a new keyword, but this is not
>insurmountable -- it was done before for generators. And GvR even
>said that he would consider this option if there enough support for
>it.
>
>----
>
>So here's my suggestions:
>
>Let's leave the location and indentation arguments behind. We're not
>making much progress on them, and I don't think there's much chance of
>swaying GvR. Reiterating all the old arguments won't get us closer to
>a syntax we're happy with.
>
>I think once the indicator argument is decided, the list-structure
>decision will fall out of it.
>
>So I'd suggest that we put all our effort into the indicator
>discussions. If you have a good argument for why a keyword is better
>than a symbol, or why a symbol is better than a keyword, please voice
>them now. And remember that 'because it's prettier' or 'because it's
>uglier' are not aguments GvR will consider. We need strong arguments,
>that argue on the basis of readability or learnability or
>maintainability, etc.
You don't think GvR goes for prettier, other things being equal?
>
>
>... and my opinion:
>
>A keyword is much more Pythonic than a symbol:
Yes, except that what we have is really nested function calls,
passing a special argument, so maybe the decorating functions
ought to look like they are being invoked as functions. I.e.,
deco1(
deco2(
arg_that_happens_to_be_created_by_a_def_statement_and_suite
))
But, since it's not an ordinary argument list, we need an alternative
to the function-calling expression trailer (...) that yet suggests calling.
Since the def defines its own end, we don't need the )) above, but we do
need a different '(' -- so I'm suggesting (= or maybe (: or (% or <<<, so
the above simply becomes
deco1(=
deco2(=
arg_that_happens_to_be_created_by_a_def_statement_and_suite
and deco1 and deco2 can just be arbitrary expressions evaluating to something
callable.
If other statement:suite blocks can be interpreted as defining arguments useful
to pass to a function, then
func(=
statement: suite
could be used in a generalized way to operate on those. The loose end here is
re/binding the function (or class, etc) name. I.e., would you want to write
foo = deco1(=
deco2(=
def foo():
pass
?
Or maybe
foo = (
deco1(=
deco2(=
def foo():
pass
)
So long as postfixed (= is just sugar for the current use case,
it doesn't matter, of course. The rebinding can be a side effect
of an expression whose value is discarded.
>
>A well chosen keyword can suggest the meaning of the construction,
>e.g. "using ... def ..." suggests that the decorators are used as part
>of the definition of the function. A symbol like '@' or '|' cannot
>easily suggest the meaning in this manner.
But deco(...) suggests calling deco with something, and that's what's happening.
We just need to distinguish the def-result-as-argument variant, IMO.
>
>For this reason, a keyword makes both reading and learning Python
>decorator syntax easier. If you encounter "using ... def ..." and
>have to guess at it's meaning, your knowledge of English "using" can
>now be applied to guess the meaning of Python "using". This is not
>true of a symbol like '@' or '|'.
see above ;-)
>
>(An additional argument might be that it will be at least /possible/
>to Google "using", but impossible to do so for "@" or "|". This was
>one of the frustrating things about Perl for me -- if I didn't know
>what a symbol did, I couldn't Google it because it wasn't a word.
>Remember that if you don't know it's a decorator, you don't know to
>search for "decorate" ;)
I do like google. How about a postfixed keyword indicator like 'munges' ;-)
deco1 munges
deco2 munges
def foo(): pass
;-)
>
>
>hoping-to-keep-this-dicussion-productive-ly-yrs,
>
hoping-to-have-added-something-useful-ly-yrs,
Regards,
Bengt Richter
More information about the Python-list
mailing list