RHS 12August2004
A package for treating parts of one variable as a whole other variable. More description to come later, but the basic idea (via some of the tests) is:
test list.stackLevels-1.1 {
Passing the name of a child into a proc to be upvar'd\
will still modify the parent
} -setup {
reset main child
} -body {
proc modify {&var} {
upvar 1 ${&var} var
set var [string toupper $var]
}
set main {a b {c d} e}
shadow child main 2
modify child
set main
} -result {a b {C D} e}
test array.stackLevels-1.1 {
Pass the child into a proc, and change it via upvar
} -setup {
reset main child
} -body {
proc modify {&var} {
upvar 1 ${&var} var
foreach {key value} [array get var] {
set var($key) [expr {$value * 20}]
}
}
array set main {a 1 b 2 c 3}
shadow child main
modify child
getArraySorted main
} -result {a 20 b 40 c 60}
test array.element-1.1 {
Shadow an array element, parent follows the 'array get'\
value of the child
} -setup {
reset main child
} -body {
array set main {a {A 1} b {B 2}}
shadow child main b
set child(B) [expr {$child(B) * 2}]
getArraySorted main
} -result {a {A 1} b {B 4}}Feel free to take a look at the code for it at http://robert.rkseeger.net/tcl/shadow/shadow.tar.gz for now. I'll write up more information on what I was trying to do, and the limits of that approach, some other time.
RS 2004-08-17: Here's a very simple version that works only on lists, by linking a scalar variable to an element of the given list, and updating the list when the variable is changed (or re-reading the element from the list when the variable is read):
proc llink {listVar index linkVar} {
upvar 1 $listVar list $linkVar link
set link [lindex $list $index]
trace add variable link {read write} [list llink'rw $listVar $index]
}
proc llink'rw {listVar index name el op} {
upvar 1 $listVar list $name link
switch -- $op {
read {set link [lindex $list $index]}
write {set list [lreplace $list $index $index $link]}
}
}# Testing:
% set list {a b c}
a b c
% llink list 2 link
% set link hello
hello
% set list
a b hello
% llink list 1 link2
% set link2 world
world
% set list
a world hello
% set list {d e f} ;# testing the other direction too
d e f
% set link2
e
% set link
fRHS Indeed, thats pretty much what the code I wrote does, but it handles fringe conditions a little better. For example:
% set list {a b c}
a b c
% llink list 2 link
% proc bob {var} { upvar $var myvar ; set myvar uhoh }
% bob link
can't set "myvar": can't read "list": no such variableAnd
% set list {a b c}
a b c
% llink list 2 link
% unset list
% set link goodbye
can't set "link": can't read "list": no such variableI wanted to make sure my code would work in those situations, as well as be able to link variables to array elements.