40.2.3.4 Lists

Tcl has a notion of lists, but as with everything it is implemented through strings. A list is a string that contains words.

A simple list is just a space separated series of strings:

     set a {one two three four five}

will set the variable a to the list containing the five strings shown. The empty list is denoted by an open and close curly bracket pair with nothing in between: {}.

For the Prolog programmer, there is much confusion between a Prolog implementation of lists and the Tcl implementation of lists. In Prolog we have a definite notion of the printed representation of a list: a list is a sequence of terms enclosed in square brackets (we ignore dot notation for now); a nested list is just another term.

In Tcl, however, a list is really just a string that conforms to a certain syntax: a string of space separated words. But in Tcl there is more than one way of generating such a string. For example,

     set fred {a b c d}

sets fred to

     "a b c d"

as does

     set fred "a b c d"

because {a b c d} evaluates to the string a b c d, which has the correct syntax for a list. But what about nested lists? Those are represented in the final list-string as being contained in curly brackets. For example:

     set fred {a b c {1 2 3} e f}

results in fred having the value

     "a b c {1 2 3} e f"

The outer curly brackets from the set command have disappeared, which causes confusion. The curly brackets within a list denote a nested list, but there are no curly brackets at the top-level of the list. (We can't help thinking that life would have been easier if the creators of Tcl would have chosen a consistent representation for lists, as Prolog and LISP do.)

So remember: a list is really a string with a certain syntax, space separated items or words; a nested list is surrounded by curly brackets.

There are a dozen commands that operate on lists.

     concat ?list list ...?

This makes a list out of a series of lists by concatenating its argument lists together. The return result is the list resulting from the concatenation.

     lindex list index

returns the index-th element of the list. The first element of a list has an index of 0.

     linsert list index value ?value ...?

returns a new list in which the value arguments have been inserted in turn before the index-th element of list.

     list ?value value ...?

returns a list where each element is one of the value arguments.

     llength list

returns the number of elements in list list.

     lrange list first last

returns a slice of a list consisting of the elements of the list list from index first until index last.

     lreplace list first last ?value ... value?

returns a copy of list list but with the elements between indices first and last replaced with a list formed from the value arguments.

     lsearch ?-exact? ?-glob? ?-regexp? list pattern

returns the index of the first element in the list that matches the given pattern. The type of matching done depends on which of the switch is present -exact, -glob, -regexp, is present. Default is -glob.

     lsort ?-ascii? ?-integer? ?-real? ?-command command? ?-increasing? ?-decreasing{? list

returns a list, which is the original list list sorted by the chosen technique. If none of the switches supplies the intended sorting technique then the user can provide one through the -command command switch.

There are also two useful commands for converting between lists and strings:

     join list ?joinString?

which concatenates the elements of the list together, with the separator joinString between them, and returns the resulting string. This can be used to construct filenames; for example:

     set a {{} usr local bin}
     set filename [join $a /]

results in the variable filename having the value /usr/local/bin.

The reverse of the join command is the split command:

     split string ?splitChars?

which takes the string string and splits it into string on splitChars boundaries and returns a list with the strings as elements. An example is splitting a filename into its constituent parts:

     set a [split /usr/local/src /]

gives a the value {{} usr local src}, a list.