# TIP 634: Remove inconsistency in variable tracing of an array
	Author:		Schelte Bron <tclcore+tip@tclcode.com>
	State:		Final
	Type:		Project
	Vote:		Done
	Created:	21-Aug-2022
	Tcl-Version:	9.0
	Tcl-Branch:	tip-634
	Keywords:	upvar,trace,array
	Vote-Results:   4/0/0 accepted
	Votes-For:      FV, KW, JN, SL
	Votes-Against:  none
	Votes-Present:  none
-----
# Abstract

This tip proposes to eliminate the "feature" that a variable trace set on an
array does not trigger when elements of the array are accessed through a
reference created via the \[upvar\] command.

# Rationale

Currently, when a link to an array element has been created using [upvar],
any variable traces set on the array as a whole will not be triggered when
the array element is accessed through the link. While this is documented in
the [upvar] manual page, it is not logical. Variable traces are generally
installed to be notified about access to a variable. If not all normal
methods to access the variable will trigger the trace, the feature cannot
really be relied upon.

# History

The reason for the current behavior seems to be that array elements have no
knowledge to which array they belong. Adding this information to each
element would have a significant memory impact. For this reason, the
decision was apparently made in the past to document the discrepancy, rather
than to fix it. This turned a bug into a feature, preventing it to be fixed
in a point load.

# Specification

Each array element has a pointer to the array's backing hashtable. Adding a
link that points to the parent array in this table will only require one
additional pointer per array. This can hopefully be considered an acceptable
expense.

With part 1 of the proposed change, a subsequent problem shows up: When the
accessed variable is a scalar, that is an alias for an array element, only
the name of the alias would currently be provided to the callback function.
In most scenarios with traces on an entire array, the callback function will
need to know the actual array element that was accessed to be able to do
something useful.

This problem is overcome by decoupling the 'name1' and 'name2' arguments
added to the callback. As before, 'name1' will still point to the variable
being accessed. But 'name2' provides the index into the array, if the
accessed variable ultimately refers to an array element.
The only noticeable difference happens in the mentioned scenario: 'name1' is
a scalar that refers to an array element. In that case 'name2' will no
longer be an empty string. Instead it provides valuable additional
information.

# Background

It is not possible to make an alias for an array index. If 'name1' refers to
an array, the index into that array has to be the same as the index into the
original array. It doesn't matter to which array the trace proc applies the
'name2' argument.

The trace proc should not attempt to determine whether 'name1' is an array
by checking if 'name2' is empty. But that was never a good strategy; the
empty string is a valid array index. The proper way has always been to use
\[array exists\]

# Reference Implementation

See branch [`tip-634`](https://core.tcl-lang.org/tcl/timeline?r=tip-634)

# Copyright

This document has been placed in the public domain.
