This page is intended eventually to become a TIP proposing an additional syntax for [trace] to allow for application-level callbacks when an array element access is performed on a scalar variable or vice versa.
Several developers have requested the ability, at either Tcl or C level, to establish callbacks that trap access to a variable that has inappropriate type. In this context, type refers to whether the variable is an array or a scalar; this is Tcl's only notion of "type" of a variable; in all other cases, "everything is a string."
The intent of this capability is to allow early experimentation with ways to represent collections other than Tcl arrays. It would allow handles to keyed lists, tree maps, vectors, database tables, and other similar structures to be stored in scalar variables within a Tcl script and still accessed as arrays. It would, however, not represent a great departure from Tcl's current mode of operation; scalars are still scalars, and arrays are still arrays. Rather, it allows user code to intercept the error that would otherwise result when a variable is accessed inappropriately (that is, an array is accessed as a scalar or vice versa). It allows the user callback to determine the results of the operation. The default is to throw the same error that is thrown today.
Today's [trace] command does not allow this type of access to be made flexibly. While using read and write traces can allow objects with array semantics to be presented at the Tcl level, these objects must have Tcl arrays representing them. This limitation can be a significant consumer of memory, and introduces problems with redundant representations of the data: the array ::env, for instance, appears as both the environment variables of the native system and as a Tcl array.
To the [trace] command, we propose adding the syntax:
trace add variable bad-array callback trace add variable bad-scalar callback
The callback function is extended from other variable traces in several ways.
Its syntax has more arguments, to wit:
callback name1 name2 op1 op2 args
The possible values of op2 include:
The callback established by this version of the trace command is invoked whenever the requested operation takes place on the given variable. For read traces, the callback is expected to return the value that the given element should take on. For write and unset traces, the return value is ignored. For array traces, the return value from the trace procedure becomes the return value from the array command that caused it to be invoked. For traces upon the trace command itself, the return value is expected to be empty for adding and removing a trace, or contain the result that is to be returned to trace info variable.
If multiple commands establish tracing on the same variable, they are invoked in the order in which they are established.
There are several special returns that can be made from the command:
[Still need to specify the C level usage for this]
AMG: I came here hoping to find tips on locating where a variable is being set. My experiments with printing all the [info frame]s inside a write trace haven't borne fruit. In GDB I'd just set a watchpoint.