Introducing Tcl 8.7 Part 3: array enhancements

Published

This is the third in a series about the new features in the recently released alpha version of Tcl 8.7. This post deals with the enhancements in Tcl 8.7 related to arrays.

To take Tcl 8.7 for a spin, you can download a pre-alpha binary for your platform. Alternatively, you can build it yourself from the core-8-branch branch in the Tcl fossil repository.

Defaulting element values with array default

The first of the new commands related to arrays, array default, is primarily a convenience command although it also has the potential to reduce memory usage in sparse arrays or when most array elements have the same value. It permits setting up a default value to be returned when an attempt is made to retrieve a non-existing element of an array.

Consider reading a set of boolean options that default to false. When processing these options, traditionally one of two approaches could be taken. In the first, the options are initialized to false and then overridden by the values specified by the user.

array set Opts {-x 0 -y 0 -z 0}
array set Opts $args
if {$Opts(-x)} {
...
}

Alternatively, a check is made for the existence of the option in the array.

if {[info exists Opts(-x) && $Opts(-x)]} {
...
}

The new array default command provides an alternative to the above by providing a means to return a default value when a array element does not exist.

The command takes the form

array default SUBCOMMAND ARRAYNAME ?ARG?

where SUBCOMMAND is one of get, set, exists and unset.

The set subcommand is used to set the default for an array.

% array default set Opts 0
% puts $Opts(-a)
0

Note this does not mean the element Opts(-a) exists.

% info exists Opts(-a)
0

The exists and get subcommands allow for introspection, checking whether an array has a default defined and to retrieve it.

% array default exists Opts
1
% array default get Opts
0

Defaults can be removed with unset.

% array default unset Opts
% array default exists Opts
0
% puts $Opts(-b)
can't read "Opts(-b)": no such element in array

In addition to convenience, use of this capability can also lead to significant memory savings in the case of large array where many elements have the same value.

Iterating with array for

The other new command related to arrays in Tcl 8.7 is array for which iterates over elements of an array. Previously, either of the following were commonly used to iterate over all elments of an array:

foreach {key value} [array get Arr] { ... }
foreach key [array names Arr] { ... }

Both these suffer from memory performance issues when arrays are large because they convert the entire contents of the array to a list.

On the other hand, the alternative array startsearch, which does not have this problem is cumbersome to use.

The new array for command, which resembles the dict for command, is simple to use like the foreach versions above but uses far less memory for large arrays.

% array for {key value} A { puts $key,$value }
a,0
b,1
c,2

One caveat to note is that the command will throw an error if the array being iterated over is modified within the iteration. Modification of arrays in mid-iteration is not very common in any case.

References

TIP 421: A Command for Iterating Over Arrays

TIP 508: New subcommand [array default]

array manpage