<div class="gmail_quote">On Sun, Dec 2, 2012 at 4:26 PM, Robert McGibbon <span dir="ltr"><<a href="mailto:rmcgibbo@gmail.com" target="_blank">rmcgibbo@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="word-wrap:break-word">By being <b>tolerant and well behaved when confronted with annotations that our library doesn't understand I</b>, I<div><div>think we can use function annotations without a short-range decorator that translates their information in some other</div>
<div>structure. If other annotation-using libraries are also willing to ignore our tabbing annotations if/when they encounter them,</div><div>then can't we all get along smoothly?</div><div><b><br></b></div><div>(For reference, the feature will look/work something like this)</div>
<div><br></div><div><b><div style="font-weight:normal"><div>In[1]: def foo(filename : tab_glob('*.txt')):  # tab completion that recommends files/directories that match a glob pattern</div><div>...          pass</div>
<div><div>...</div><div>In[2]: foo(<TAB></div><div>'a.txt'        'b.txt'</div><div>'c.txt'         'dir/'</div></div></div></b></div></div></div></blockquote><div><br>You're missing the other key reason for requiring decorators that interpret function annotations: they're there for the benefit of *readers*, not just other software. Given your definition above, I don't know what the annotations are for, except by recognising the "tab_glob" call. However, that then breaks as soon as the expression is put into a named variable earlier in the file:<br>
<br><div>    def foo(filename : text_files): # What does this mean?<br></div><div>        pass</div><br>But the reader can be told *explicitly* what the annotations are related to via a decorator:<br><br>    @tab_expansion<br clear="all">
</div></div><div>    def foo(filename : text_files): # Oh, it's just a tab expansion specifier<br></div><div>        pass<br><br>Readers no longer have to guess from context, and if the tab_expansion decorator creates IPython-specific metadata, then the interpreter doesn't need to guess either.<br>
<br>(Note that you *can* use ordinary mechanisms like class decorators, metaclasses, post-creation modification of classes and IDE snippet inclusion to avoid the need to type out the "this is what these annotations mean" decorator explicitly. However, that's just an application of Python's standard abstraction tools, rather than a further special case convention)<br>
<br>Mixing annotations intended for different consumers is a fundamentally bad idea, as it encourages unreadable code and complex dances to avoid stepping on each other's toes. It's better to design a *separate* API that supports composition by passing the per-parameter details directly to a decorator factory (which then adds appropriate named attributes to the function), with annotations used just as syntactic sugar for simple cases where no composition is involved.<br>
<br>The important first question to ask is "How would we solve this if annotations didn't exist?" and only *then* look at the shorthand case for function-annotations. For cases where function annotations make code more complex or less robust, *don't use them*.<br>
<br>Cheers,<br>Nick.<br><br></div>-- <br>Nick Coghlan   |   <a href="mailto:ncoghlan@gmail.com">ncoghlan@gmail.com</a>   |   Brisbane, Australia<br>