TIP #77: Support for Nested Paired Item Lists
_____________________________________________________________________________
TIP:	77
Title:	Support for Nested Paired Item Lists
Version:	$Revision: 1.3 $
Authors:	Christian Williams <xian@planetoutpartners.com>
State:	Withdrawn
Type:	Project
Tcl-Version:	8.5
Vote:	Pending
Created:	Fri Dec 07 00:00:00 UTC 2001
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 [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
http://sf.net/tracker/?func=detail&aid=491070&group_id=10894&atid=310894
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.
_____________________________________________________________________________
Colophon
TIP AutoGenerator - written by Donal K. Fellows