TIP 677: Constant Variables

Login
Author:         Donal Fellows <[email protected]>
State:          Final
Type:           Project
Vote:           Done
Created:        29-Jun-2023
Tcl-Version:    9.0
Tcl-Branch:     tip-677
Vote-Summary:	4/0/2
Votes-For:	DKF, BG, MC, KW
Votes-Against:	
Votes-Present:	SL, DGP

Abstract

This TIP proposes a way to define variables as if they were named constants in Tcl code.

Rationale

While Tcl doesn't need that many constants by comparison with many other languages, as we can use symbolic names directly (witness how we handle flags to open), there are still the occasional thing where we want to have a value in a variable that isn't written to again.

An example of such is where you store a complex regular expression in a variable in order to give it a more mnemonic name. Rewriting such is going to be an infrequent action, as it will require reworking all the code that uses it as well; for the duration of the execution of a procedure or existence of a namespace, the variable is not to be changed.

It's possible to effectively make such variables by using a trace to set a variable back, but that's quite messy.

The advantage of having a special mechanism for this is that it is much easier to see the intention on the part of the author of the code that the value in a variable not be ever modified during the running of the code. This will also permit more efficient code generation at some point; a known constant is much more likely to be analysable during the generation of bytecode (or during any other possible future execution strategy).

Specification

This TIP proposes a new command, const that defines a "constant" variable in the current scope. It may be used either in a procedure (or method or lambda) to define a constant variable with local scope, or in a namespace (or at the top level) to define a constant variable with scope to that namespace (according to usual variable scoping rules).

The varName may be a qualified name. If const is used with a qualified name in a procedure, it does not make a local alias to that name. (That is, const does not duplicate namespace upvar.)

The varName must not be the name of an array element, even via upvar. Arrays may not contain constant variables by any means. The result of the const command will be the empty string. The varName may be an alias (upvar, global, etc) to a variable in another scope; it is the target of that alias that will become the constant.

A constant variable may be read like any other variable (but the bytecode compiler may replace its use in code with something more efficient).

A constant variable may not be written to or unset, except if the local scope or namespace is being deleted.

Write and unset traces will not fire on failed writes to or unsets of a constant variable, except (for unset traces only) when the containing scope is being deleted. The call to const on an existing constant will not fire a write trace, but a call when the variable is not defined will fire a write trace on the variable if one is defined.

The variable must not exist prior to const creating a constant variable (unless it is a constant variable; in that case, const silently does nothing). That is, $varName must be in a state where it will fail unless it is a constant.

Introspection

Two info subcommands are provided for working with constants:

Returns a lists of constants in the current scope, optionally matching against pattern. (It's info vars with additional filtering by whether the variable is a constant.)

Returns a boolean value indicating whether the varName resolves to a variable that is a constant.

Known Consequence

If a constant variable is created in the global namespace, it necessarily will endure with that value until the interpreter terminates.

Implementation

See the tip-677 branch.

Copyright

This document has been placed in the public domain.