TIP #77: SUPPORT FOR NESTED PAIRED ITEM LISTS =============================================== Version: $Revision: 1.3 $ Author: Christian Williams State: Withdrawn Type: Project Tcl-Version: 8.5 Vote: Pending Created: Friday, 07 December 2001 URL: https://tip.tcl-lang.org77.html Post-History: Obsoleted-By: TIP #111 ------------------------------------------------------------------------- ABSTRACT ========== Tcl arrays can be transformed to and from lists using the /array get/ and /array set/ commands. This TIP proposes a new command for working directly these paired lists, and extending them to allow nesting in a manner analogous to [TIP #22]. RATIONALE =========== Tcl lists provide only ordinal access to their items; often it makes more sense to access items by pre-assigned descriptive names. This can be easily accomplished with Tcl arrays. Consider these alternatives: set urlList { http tcl.activestate.com 80 /index.html } array set urlArray { proto http host tcl.activestate.com port 80 uri /index.html } Clearly the array approach promotes more readable code (/$urlArray(host)/ versus /[lindex $urlList 1]/). However, it's quite unwieldy and sometimes expensive to use arrays to access members of many sets of structured data, particularly when that data contains nested structures. Consider this structured data: set data { text {ignored-data} valid-styles { justification {left centered right full} font {courier helvetica times} } } Extracting items from structures like this can be accomplished by multiple /array set/ commands: array set dataArray $data array set validStylesArray $dataArray(valid-styles) puts "Justification: $validStylesArray(justification)" To modify an item in /struct/, we need some pretty ugly code: array set dataArray $struct array set validStylesArray $dataArray(valid-styles) set validStylesArray(justification) {left} set dataArray(valid-styles) [array get validStylesArray] set data [array get dataArray] Clearly, all this setting and getting of arrays imposes a rather high overhead; many variables are created and moved around. Also, if this is occurring in a loop, then care must be taken to unset the /dataArray/ and /validStylesArray/ arrays first. In contrast, a C programmer may expect that code to look more like this: data->valid-styles->justification = 'left'; Extending Tcl with a command supporting nested, paired item lists would permit very efficient and readable handling of these useful data structures. SPECIFICATION =============== Under this proposal, a new command named /pair/ (referring to the pairs of name/value list items it works with) would be added to the Tcl core. A well-formed paired list is defined as a well-formed Tcl list whose length is evenly divisible by two. In each pair of list items, the first item gives the name of the pair, and the second gives the value. Paired lists may be nested by placing a valid paired list in the second (value) item of any pair. Note that the pairs are not grouped together into a two-item list as in TclX's keyed lists. Tcl's /array get/ command returns a well-formed paired list. The syntax for the new /pair/ command would be: pair option variable node ?newValue? Valid values for the /options/ argument include /get/, /set/, /unset/, /exists/, and /append/. These subcommands are equivalent to the existing Tcl commands of the same names. The /variable/ argument is the name of a Tcl variable; it is always referred to by name, not by its value (that is, no /$/). Generally, the variable would contain a well-formed, and optionally nested, paired list. The /node/ argument is a well-formed Tcl list of zero or more items specifying the route to the item we're interested in. For example: set data { text {ignored-data} valid-styles { justification {left centered right full} font {courier helvetica times} } } puts "Justification: [pair get data {valid-styles justification}]" displays "Justification: left centered right full". If the /data/ argument contains zero items, then the "root" node of the variable is targeted -- that is, the entire variable: pair set node {} new-value puts $node displays "new-value". If a non-existent node is targeted using the /get/ or /unset/ options, an error is returned: unset x pair get x {first second third} -> no such value If a non-existent node is targeted using the /set/ or /append/ options, the node, and any parent nodes, are created. unset x pair set x {first second third} value puts $x displays "first {second {third value}}" The /exists/ option mimics Tcl's /info exists/ command: set x {name value} pair exists x name -> 1 pair exists x name2 -> 0 The /set/ and /append/ options return the value of the node that has just been set, not the value of the variable. This would seem to be more in keeping with the intent of Tcl's /set/ and /append/ commands' return values than duplicating the exact behaviour: puts [pair set x {first second third} value] displays "value". An error is returned if a variable is passed to the /pair/ command which doesn't contain a well-formed paired Tcl list at any point on the way to the node specified by the /node/ argument: set x {name value thirdarg} pair get x name -> list must have an even number of elements If there are traces registered on the variable passed to the /pair/ command, they are triggered in the same manner as Tcl's /set/ and /append/ commands. Note that the /append/ option triggers only write triggers, not read triggers. Note that the /set/ and /append/ options both return the value of the node specified, and the /newValue/ argument is optional in both cases, making the /get/ option redundant. The /get/ command is included to improve readability. If the variable passed to /pair/ doesn't exist, it will be created if the option is 'set' or /append/; the /exists/ option will always return a /0/; the /get/ option will return an error. If a paired list contains multiple pairs with identical names, the pair occurring later in the list is targeted. This is specified to mimic the behaviour of /array set/: set x "name value1 name value2" pair get x name -> value2 array set arrX $x set arrX(name) -> value2 REFERENCE IMPLEMENTATION ========================== There should be a public C API for working with nested paired lists. The supplied reference code currently does not provide this. NOTES ======= It would be nice to mimic Tcl 8.4's new /unset -nocomplain/ behaviour. SIDE EFFECTS ============== Whether the result of the pair operation is successful, the underlying Tcl_Obj that represents the list argument may have its internal representation invalidated or changed to that of a list. COPYRIGHT =========== This document has been placed in the public domain. ------------------------------------------------------------------------- TIP AutoGenerator - written by Donal K. Fellows