A fast C extension for parsing procedure arguments written by Cyan Ogilvie. Available from . Presented at the Tcl 2016 conference. See the paper (PDF) and slides .

Comparison with [argparse]

AMG: [parse_args] is remarkably similar to [argparse]. I promise I never knew about [parse_args] until today, yet somehow I ended up making something quite like it. This tells me the functionality is sorely needed and possibly worth adding to the Tcl core.


[parse_args] and [argparse] both seek to accomplish the same task. Both are commands rather than modifications to [proc], which makes them quite flexible. [parse_args] cites parsing the return value of [yield] as an example of parsing something other than the arguments to a proc.

[parse_args] and [argparse] both support switches and parameters. Switches are named with a leading minus and can be defined to take an argument. In addition to being named, each switch or parameter may be defined further to set various attributes.

-required and -default appear to work the same in [parse_args] and [argparse].

Both [parse_args] and [argparse] support --.


[parse_args] is written in C, and [argparse] is written in Tcl. I plan to rewrite [argparse] in C and expose a stubs-enabled C API.

[parse_args] takes two parameters: the argument list to parse, followed by the signature definition. [argparse] takes any number of switches followed by the element definition (a.k.a. signature definition), then optionally the argument list to parse. If the argument list is omitted, the value of the args variable is parsed.

[parse_args] defines switches and parameters using a dict. The key is the switch or parameter name, and the value is the list of definition attributes, expressed as a list of switches. Instead of a dict, [argparse] uses a list of lists, where the first element is the switch or parameter name, and subsequent elements are definition attributes, also expressed as switches. I chose this approach because most switches and parameters don't need any extra definition attributes, and I wanted to avoid repeatedly typing "{}".

[argparse] provides a shorthand syntax to reduce the need for definition attributes. -argument, -optional, -required, -catchall, and -upvar can be written as single-character flags appended to the switch or parameter name. Technically, -switch and -parameter also have shorthand, i.e. prefixing or not prefixing the switch or parameter name with minus, but this isn't much of a shorthand because it's the normal operation for [parse_args]. [argparse] also provides shorthand for -alias, though [parse_args] does not have -alias capability.

When a switch or parameter uses the -upvar switch (or its shorthand), [argparse] uses [upvar] to link the local variable for the switch or parameter to the caller variable named by the value of the switch or parameter. [parse_args] does not have this capability.

[argparse] has the -long and -equalarg switches which allow --switch=argument alternate syntax. This is useful when parsing command-line arguments because many users are accustomed to GNU long options.

[argparse] matches unambiguous switch name prefixes, though this facility can be disabled with the -exact switch.

[parse_args] requires that all switches appear before all parameters. [argparse] requires this by default but allows the two to be interspersed when the -mixed switch is used.

[argparse] has pass-through capabilities to store either unparsed or normalized switches and/or parameters into a variable for further processing, e.g. passing along to another procedure.

[argparse] can either write its results to variables or, when given -inline, return a dict.

[parse_args] has the -multi switch to explicitly identify cases where multiple switches share the same -name. [argparse] automatically detects sharing of the same -key (analogous to -name). [parse_args] automatically changes the -default in this situation to be the switch name, whereas [argparse] requires the -default to be explicitly changed. (I plan to fix this. The -default is empty string, which is useless in this case.)

When multiple switches or parameters share the same name (or key), [parse_args] lets the last one win, whereas [argparse] throws an error due to having automatically created -forbid constraints. Perhaps I could add a switch enabling or disabling this behavior.

[parse_args] has the -boolean switch, which appears to work the same as writing "-value 1 -default 0" with [argparse]. (I think I'll add -boolean.)

[parse_args] has -validate and -enum, but [argparse] does not. (Yet! I'm always looking for good ideas to steal.) [argparse] has another kind of validation checking for combinations of switches and parameters: -required, -standalone, -require, -forbid, and -reciprocal.

[parse_args] has -# for comments, but [argparse] does not. My feelings on this are complex and would be a distraction, so let's leave this alone for now.

With -optional, [argparse] allows switches to have optional arguments, e.g. in the case of Tk widget configure commands.

[argparse] allows optional, defaulted, and catchall parameters to appear in any order. I'm not sure if [parse_args] has similar capability.

[parse_args] has the -args switch to control how many arguments to take as the value of a switch. [parse_args] allows zero arguments, one argument, or the entire remainder of the argument list.

[parse_args] has the -name switch which behaves the same as the [argparse] -key switch. I chose the term "key" because "name" was too generic for clear documentation, whereas "key" was a better fit for the fact that [argparse] has an -inline mode in which it returns a dict.