A
single assignment variable is a variable that can be assigned a value no more than once. Single assignment variables can be used to emulate
[constants
] or to ensure correctness. In Tcl, you can prevent variables from being reassigned with
trace.
Implementation edit
dbohdan 2015-11-05: The following is my implementation of single assignment variables.
Usage
val foo 5
puts $foo ;# prints "5"
incr foo ;# error
or
val foo
# ...
set foo 5
puts $foo ;# prints "5"
incr foo ;# error
Code
namespace eval ::singleAssignment {
variable version 0.1.0
}
proc ::singleAssignment::traceAssigned {name1 name2 op} {
error "variable \"$name1\" can't be modified"
}
proc ::singleAssignment::traceUnassigned {name1 name2 op} {
uplevel 1 [list trace remove variable \
$name1 {write unset} \::singleAssignment::traceUnassigned]
uplevel 1 [list trace add variable \
$name1 {write unset} \::singleAssignment::traceAssigned]
}
proc ::singleAssignment::val args {
switch -exact -- [llength $args] {
1 {
lassign $args varName
}
2 {
lassign $args varName value
}
default {
set procName [dict get [info frame 0] proc]
error "wrong # args: should be \"$procName name ?value?\""
}
}
if {[uplevel 1 [list info exists $varName]]} {
error "variable \"$varName\" is already set"
}
uplevel 1 [list trace add variable \
$varName {write unset} ::singleAssignment::traceUnassigned]
if {[info exists value]} {
uplevel 1 [list set $varName $value]
}
}
namespace path ::singleAssignment