[Python-3000] Draft pre-PEP: function annotations (original) (raw)
Phillip J. Eby pje at telecommunity.com
Sat Aug 12 23:10:17 CEST 2006
- Previous message: [Python-3000] Draft pre-PEP: function annotations
- Next message: [Python-3000] Draft pre-PEP: function annotations
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
At 12:38 PM 8/12/2006 -0700, Paul Prescod wrote:
Phillip. I'm having trouble following the discussion. I briefly caught up when Talin got very concrete with syntax and I would appreciate if you could offer some correspondingly remedial training.
Talin's example is that metadata inventor A documents that his/her users should use this syntax for parameter docstrings: def myfunc( x : "The x coordinate", y : "The y coordinate" ) ... Then metadata inventor B documents this his/her users should use this syntax for getopt strings: class MyHandler( CommandLineHandler ): @getopt def list( infile:"i" = sys.stdin, outfile:"o" = sys.stdout ): Now the user is faced with the challenge of making these two work together in order to get the best of both worlds. What does the user type?
As long as both inventors used overloadable functions, the user can type almost anything they want to, as long as:
- It's consistent,
- It's unambiguous, and
- They've defined the appropriate overloads.
For example, they might use a 'docopt' class that allows both to be specified, or a pair of 'doc' and 'opt' objects in a list.
The mechanism of overloading, function dispatching etc. is uninteresting to me until I understand what goes in the user's Python file. Syntax is important.
Indeed it is. Hence the importance of not forcing some particular semantics, so as to allow the user to use the types and semantics of their choosing.
By the way, it should be understood that when I say "overloadable function", I simply mean some type-extensible dispatching mechanism. If you exclude built-in types from consideration, and simply have special attribute or method names, then duck typing works just as well. You can have decorators that use hasattr() and such to do their dirty work.
It's only if you want to have sensible meaning for built-in types that there even begins to be an illusion that conflicts are an issue. However, the only built-in types likely to even be used in such a way are lists, dictionaries, tuples, and strings. If there's more than one way to interpret them, depending on the operation, their use is inherently ambiguous, and it's up to the person combining them to supply the differentiation.
However, if you have:
def myfunc( x : doc("The x coordinate"), y : doc("The y coordinate") )There is no ambiguity. Likewise:
def cat( infile:opt("i") = sys.stdin, outfile:opt("o") = sys.stdout ):is unambiguous. And the interpetation of:
def cat(infile: [doc("input stream"), opt("i")] = sys.stdin,
outfile: [doc("output stream"), opt("o")] = sys.stdout
):is likewise unambiguous, unless the creator of the documentation or option features has defined some other interpretation for a list than "recursively apply to contained items". In which case, you need only do something like:
def cat(infile: docopt("input stream", "i") = sys.stdin,
outfile: docopt("output stream", "o") = sys.stdout
):with an appropriate definition of methods for the 'docopt' type.
Since many people seem to be unfamiliar with overloaded functions, I would just like to take this opportunity to remind you that the actual overload mechanism is irrelevant. If you gave 'doc' objects a 'printDocString()' method and 'opt' objects a 'setOptionName()' method, the exact same logic regarding extensibility applies. The 'docopt' type would simply implement both methods.
This is normal, simple standard Python stuff; nothing at all fancy. The only thing that overloaded functions add to this is that they allow you to (in effect) add methods to existing types without monkeypatching. Thus, you can define overloads for built-in types, and types you didn't implement yourself. Even if overloaded functions didn't exist, it wouldn't be necessary to invent them just to allow arbitrary annotation semantics! It simply requires that operations that use annotations always follow the "tell, don't ask" pattern, whether it's done by duck typing, EAFP, or overloaded functions.
- Previous message: [Python-3000] Draft pre-PEP: function annotations
- Next message: [Python-3000] Draft pre-PEP: function annotations
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]