====== if false { ====== [wdb] on page [tcl9var], we discussed unification of namespaces of commands and variables. Main argument against it was broken compatibility to current variables. Here a try to use it with source-compatibility to Tcl 8.x: ====== } package require Tcl 8.5 # because of dict namespace eval tcl9var { variable tcl9val {} namespace export tcl9var } proc tcl9var::handleVar {name {cmd get} args} { variable tcl9val if {$cmd in {set unset}} then { dict $cmd tcl9val $name {*}$args } else { dict $cmd $tcl9val $name {*}$args } } proc tcl9var::tcl9var {name args} { variable tcl9val set ns [uplevel namespace current] if {$ns eq "::"} then { set n ::$name } else { set n ${ns}::$name } dict set tcl9val $n {*}$args uplevel 1 [list proc $name args { ::tcl9var::handleVar [ namespace origin [lindex [info level 0] 0] ] {*}$args }] $name } namespace import tcl9var::tcl9var if false { ====== As an example, we use a ''simple'' variable: ====== % tcl9var a apple apple % puts "my [a] is red" my apple is red % a set [a]tree ::a appletree % puts "my [a] is high" my appletree is high % ====== In one way we can build a variable as a dictionary: ====== % tcl9var fruit a apple a apple % tcl9var fruit o orange a apple o orange % fruit a apple o orange % fruit get a apple o orange % fruit get a apple % fruit get o orange % fruit set o mango ::a appletree ::fruit {a apple o mango} % fruit get o mango ====== Care must be taken if the "raw value" of a variable has an odd number of elements -- then dict usage fails. **Compatibility issues** With usage as dict, we can introduce a special variable '''$''' internally built as dictionary as follows: ====== % tcl9var $ start 0 start 0 % tcl9var $ end 10 start 0 end 10 % $ get start 0 % $ get end 10 % ====== Now, the syntax '''$abc''' shall shall be expanded by proc ''expand$'' to the appropriate call '''[[$ get abc]]'''. With this expansion of cmd lines, you can make things like $hello, or $hello(world), or $hello(world)(of_tcl_programming), i.e. true multi-dimensional arrays. ====== } proc expand$ str { if {![regexp {[$]([[:alnum:]_]+)((?:[(].*[)])*)} $str m v b]} then { return $str } set matchStart [string first $m $str] set matchEnd $matchStart incr matchEnd [string length $m] incr matchStart -1 append result [string range $str 0 $matchStart]\ "\[$ get $v" foreach x [split [string trim [string map {( ""} $b] )] )] { append result " [list $x]" } append result \]\ [expand$ [string range $str $matchEnd end]] } if false { ====== Example: ====== % expand$ {This $a stems from $your(garden)} This [$ get a] stems from [$ get your garden] % % expand$ {test call: $a(b)(c)(d)} test call: [$ get a b c d] % ====== An appropriate procedure [set] can be defined as needed by backwards compatibility. See tcl9set below. ====== } proc tcl9set {name args} { regexp {^([^(]+)((?:[(].*[)])*)} $name - names parens foreach {- sub} [regexp -inline -all {[(]([^)]+)[)]} $parens] { append names " [list $sub]" } if {[llength $args] == 0} then { uplevel "$ get $names" } elseif {[llength $args] == 1} then { if {[uplevel info command $] eq ""} then { uplevel "tcl9var $ [list $name] {}" } uplevel "$ set $names [list {*}$args]" uplevel "$ get $names" } else { return -code error [list tcl9set requires 1 or 2 arguments!] } } if false { ====== Example: ====== % tcl9set fruit(a) apple apple % tcl9set fruit(l) lemon lemon % tcl9set fruit(l) lemon % tcl9set fruit a apple l lemon ====== Iterator [foreach] shall make use of '''$''' as well as command [dict with] as well as argument assignment in [proc]edures. So no unwanted collision if a variable name equals command name. Consequences: syntax with '''$''' works as usual. Semantics of dict provided by variable methods. Shorter source code. Unsolved problems: as '''$''' is a procedure here, it cannot (yet) be local to a [proc] or [apply] closure. Perhaps subject for a [TIP]? (I'm not sure.) ====== } ====== ---- !!!!!! %| [Category Suggestions] | [Category Concept] |% !!!!!!