TIP 508: New subcommand [array default]

Login
FlightAware bounty program for improvements to Tcl and certain Tcl packages.
Author:         Frédéric Bonnet <fredericbonnet@free.fr>
State:          Draft
Type:           Project
Vote:           
Created:        13-May-2018
Post-History:   
Keywords:       Tcl,array
Tcl-Version:	8.7

Abstract

This TIP proposes a new [array default] subcommand that allows default values for arrays, causing that value to be returned any time an attempt is made to access an element of the array that isn't present.

Rationale

For its most basic usages, a Tcl array variable can be seen as a collection of scalar variables. However, an array also has its own existence as a variable and provides specficic actions on itself and on its elements. For exampe, the regular way to check for a variable existence is to use the [info exists] command, and this is true for both arrays and scalars (including array elements); likewise, the [set] command is used to read and write the value of a scalar vars and array elements, however array variables have no value in themselves but provide a way to get and set several of its elements at once.

For more advanced usages, one must get past the simple 'collection of scalars' viewpoint. A typical example is sparse arrays: at present, an implementation requires a combination of [array exists] (or [info exists]) and [set]: the former to test the presence of a key in an array, the latter to get or set the actual value, and in this order. Failure to do so is likely to cause runtime errors.

This document therefore proposes to add a new [array default] subcommand in order to support such advanced usages. Sparse arrays built on this new feature will be simplerw, more robust, faster, all the while being memory efficient.

Specification

A new array default subcommand will be created with the following syntax:

array default option arrayName ?arg? : Default value management.

The following option values are supported:

  • array default get arrayName: Get arrayName default value. Raise an error if arrayName is not an array variable or if it has no default value.
  • array default set arrayName value: Set arrayName default value. If the variable arrayName does not already exist, it is created with an empty array value. Raise an error if arrayName is an existing scalar variable or an invalid array name.
  • array default exists arrayName: Test whether arrayName has a default value. Return false if arrayName does not exist. Raise an error if arrayName is not an array variable.
  • array default unset arrayName: Unset arrayName default value. Does nothing if arrayName does not exist. Raise an error if arrayName is not an array variable.

Examples

Initial state:

% array exists var
0
% array default exists var
0
% array default get var
"var" isn't an array
% set var(a)
can't read "var(a)": no such variable

Create array with one entry:

% set var(a) 1
1
% array exists var
1
% array default exists var
0

Attempt to read missing entry:

% set var(b)
can't read "var(b)": no such element in array

Add default value:

% array default set var 0
% array default exists var
1
% array default get var
0

Default value is only used by missing entries:

% info exists var(a)
1
% set var(a)
1
% info exists var(b)
0
% set var(b)
0

You can lappend to a missing entry and it will behave as expected:

% lappend var(b) 2
0 2
% info exists var(b)
1

Changing the default value only impact missing entries:

% info exists var(c)
0
% set var(c)
0
% array default set var 9999
% array default get var
9999
% set var(a)
1
% set var(b)
0 2
% set var(c)
9999

Default values don't show in entry lists or iterations:

% array names var
a b
% array get var
a 1 b {0 2}
% array for {key value} var {puts "$key => $value"}
a => 1
b => 0 2
% parray var
var(a) = 1
var(b) = 0 2	

Unsetting the default value will only invalidate missing entries:

% array default unset var
% set var(a)
1
% set var(b)
0 2
% info exists var(c)
0
% set var(c)
can't read "var(c)": no such element in array

Setting the default value on a non-existing variable implicitly creates an array variable:

% array exists var2
0
% array default set var2 1234
% array exists var2
1

Implementation

The proposed implementation is available on branch tip-508 in the Tcl Fossil repository.

Copyright

This document has been placed in the public domain.