<div class="gmail_quote">On Thu, Dec 6, 2012 at 5:22 AM, Guido van Rossum <span dir="ltr"><<a href="mailto:guido@python.org" target="_blank">guido@python.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
- Composability (Nick's pet peeve, in that he is against it). I<br>
propose that we reserve plain tuples for this. If an annotation has<br>
the form "x: (P, Q)" then that ought to mean that x must conform to<br>
both P and Q. Even though Nick doesn't like this, I don't think we<br>
should do everything with decorators. Surly, the decorators approach<br>
is good for certain use cases, and should take precedence if it is<br>
used. But e.g. IDEs that use annotations for suggestions and<br>
refactoring should not require everything to be decorated -- that<br>
would just make the code too busy.<br></blockquote><div><br>I'm not against using composition within a particular set of annotation semantics, I'm against developing a convention for arbitrary composition of annotations with *different* semantics.<br>
<br>Instead, I'm advocating for the following guidelines to avoid treading on each others toes when experimenting with annotations and to leave scope for us to define standard annotation semantics at a future date:<br>
<br>1. Always use a decorator that expresses the annotation semantics in use (e.g. tab completion, type descriptions, parameter documentation)<br>2. Always *move* the annotations out to purpose-specific storage as part of the decorator (don't leave them in the annotations storage)<br>
3. When analysing a function later, use only the purpose-specific attribute(s), not the raw annotations storage<br>4. To support composition with other sets of annotation semantics, always provide an alternate API that accepts the per-parameter details directly (e.g. by name or index) rather than relying solely on the annotations<br>
<br>The reason for this is so that if, at some future point in the time, python-dev agrees to bless some particular set of semantics as *the* meaning of function annotations (such as the type hinting system being discussed), then that won't break anything. Otherwise, if people believe that it's OK for them to simply assume that the contents of the annotations mean whatever they mean for their particular project, then it *will* cause problems further down the road as annotations written for one set of semantics (e.g. tab completion, parameter documentation) get interpreted by a processor expecting different semantics (e.g. type hinting).<br>
<br>Here's how your example experiment would look under such a scheme:<br><br>    from experimental_type_annotations import type_hints, Int, Str, Float<br>
<br>    # After type_hints runs, foo.__annotations__ would be empty, and the type<br>    # hinting data would instead be stored in (e.g.) a foo._type_hints attribute.<br>    @type_hints<br>    def foo(a: Int, b: Str) -> Float:<br>
        <blah><br><br>This is then completely clear and unambigious:<br>- readers can see clearly that these annotations are intended as type hints<br>- the type hinting processor can see that there *is* type hinting information available, due to the presence of a _type_hints attribute<br>
- other automated processors see that there are no "default" annotations 
(which is good, since there is currently no such thing as "default" 
annotation semantics)<br><br>Furthermore, (as noted elsewhere in the thread) an alternate API can then easily be provided that supports composition with other annotations:<br><br>    @type_hints(Int, Str, _return=Float)<br>
    def foo(a, b):<br>        <blah><br></div></div><br>Cheers,<br>Nick.<br clear="all"><br>-- <br>Nick Coghlan   |   <a href="mailto:ncoghlan@gmail.com">ncoghlan@gmail.com</a>   |   Brisbane, Australia<br>