Rich <ri...@example.invalid> writes:
> Cecil Westerhof <
Ce...@decebal.nl> wrote:
>> So I am on the right way, but why does unset not trigger an error?
>
> Because of this:
> trace add variable name ops commandPrefix
> ^^^^^^^^^^^^^
> and this:
> Any errors in unset traces are ignored.
>
> part of the trace documentation.
So it is impossible to generate an error? Also when using an
commandPrefix?
> You are passing a "script" to your trace invocations. They need to be
> commandPrefix'es instead (i.e. they need to call into proc's that take
> a set of arguments).
>
> Compare:
>
> $ rlwrap tclsh
> % set x test
> test
> % trace add variable x unset {puts UNSET}
> % unset x
> % set x test
> test
> % proc cmdprefix {args} {puts "UNSET args='$args'"}
> % trace add variable x unset [list cmdprefix hello from the trace]
> % unset x
> UNSET args='hello from the trace x {} unset'
> %
I tried:
proc readonly {varname value} {
proc cmdprefix {args} {
puts "UNSET args='$args'"
error "Variable is readonly"
}
upvar ${varname} var
set var ${value}
trace add variable var write "error \"${varname} is readonly\";"
trace add variable var unset [list cmdprefix]
}
But this only results in:
UNSET args='ROfoo {} unset'
The following does work:
proc readonly {varname value} {
proc cmdprefix {args} {
puts "[lindex $args 0] is readonly"
exec [exit 1]
}
upvar ${varname} var
set var ${value}
trace add variable var write "error \"${varname} is readonly\";#"
trace add variable var unset [list cmdprefix]
}
It is a nasty hack, but I think that it is better as not cancelling on
an unset.
And combined this gives:
proc readonly {varname value} {
proc cmdprefix {args} {
set message "[lindex ${args} 0] is readonly"
set type [lindex ${args} 2]
if {${type} eq "unset"} {
puts "${message} and cannot be unset"
exec [exit 1]
}
error ${message}
}
upvar ${varname} var
set var ${value}
trace add variable var {unset write} [list cmdprefix]