[slebetman]: This implements what I'd call C-like syntax for numbers in Tcl. Basically, this means that not only can you use infix assignment like ''x = $y * 2'' but you also need to declare the variables before using them. There are other implementations of this available somewhere in this wiki, mostly by [Richard Suchenwirth]. Prompted by [GWM] I thought I'd dig up my very simple implementation which have been floating around usenet (google "syntax expressiveness"). Anyway, here's the code: proc cleanupVar {name1 name2 op} { if {![uplevel 1 [list info exists $name1]]} { rename $name1 {} } } proc var {name {= =} args} { upvar 1 $name x if {[llength $args]} { set x [expr $args] } else { set x {} } proc $name args [subst -nocommands { upvar 1 $name $name if {[llength \$args]} { set $name [expr [lrange \$args 1 end]] } else { return $$name } }] uplevel 1 [list trace add variable $name unset cleanupVar] } The following is an example of how to use var: proc test {} { var x var y = 10 x = $y*2 return $x } puts [test] Another feature is that the variables actually exists in local scope even though their associated commands exists in global scope. This means that the variables can be used recursively: proc recursiveTest {x} { var y = $x - 1 if {$y > 0} { recursiveTest $y } puts $y } recursiveTest 10 should output the numbers 0 to 9. Another test: proc test2 {} { var x = 10 puts "this x belongs to test2 = $x" } proc test3 {} { var x = 100 test2 puts "this x belongs to test3 = $x" } test3 output: this x belongs to test2 = 10 this x belongs to test3 = 100 [Larry Smith] All of this would be so much tidier if it were possible to declare local procs. ''[escargo] 4 Feb 2007'' - Might it make more sense for the default value of a declare var to be 0 (or, since these are supposed to be reals, 0.0)? [slebetman]: I prefer a default value that is not a number. If you want to initialise it to 0 then declare it as: var x = 0 Besides, these aren't ''supposed'' to be reals. They're regular Tcl ''variables'' with [expr] built-in. It's important to remember that because: var x = 1 / 2 is '''not''' 0.5 but 0. [NEM]: A few comments. Firstly, the advice to always [brace your expr-essions] applies here too: % var x = "foo" eq "bar" invalid bareword "foo" in expression "foo eq bar"; should be "$foo" or "{foo}" or "foo(...)" or ... The other performance and precision benefits also apply, so you should really write: var x = {"foo" eq "bar"} However, this doesn't actually work as "args" applies more quoting, resulting in x being assigned the literal string {"foo" eq "bar"}. It will also go wrong with any variable references. We can fix this with an [uplevel], and we can also simplify the var proc considerably using [interp alias]es and setting the trace through the upvar alias: proc var {name {= =} args} { upvar 1 $name x if {[llength $args]} { set x [uplevel 1 [linsert $args 0 expr]] } interp alias {} $name {} ::var $name trace add variable x unset cleanupVar return $x } [Lars H]: It's probably unnecessary to recreate the alias every time the variable is set, but indeed this is the kind of command that should be an alias. I think [NEM]'s variant is buggy with respect to recursion however, as the command disappears the first time a variable by that name is unset. Try changing test3 to proc test3 {} { var x = 100 test2 x = $x + 1 puts "this x belongs to test3 = $x" } to see the problem. The following addresses these issues, most of the time. proc var_set {name {= =} args} { uplevel 1 [list ::set $name [uplevel 1 [linsert $args 0 ::expr]]] } proc var {name {= =} args} { upvar 1 $name x if {[llength $args]} { set x [uplevel 1 [linsert $args 0 ::expr]] } set cmd [uplevel 1 {::namespace current}]::$name if {![llength [interp alias {} $cmd]]} then { interp alias {} $cmd {} ::var_set $name trace add variable x unset [list ::interp alias {} $cmd {}] } return $x } (It is still possible to break it by [uplevel]ling an [unset] for the outer variable, but as long as unsetting happens because procedures return it should be OK. ''[slebetman] Note that unsetting the "local" should be OK, at least in the original code at the top of this page. Just don't unset the variable of the same name at uplevel 1.'') [NEM]: Lars, I don't see the problem. My variant produces: this x belongs to test2 = 10 this x belongs to test3 = 101 Is that not correct? ---- See also: [infix], [Gadgets], [Radical Language Modification] and [Let unknown know] [A little math language] - [L] ---- [[ [Category Syntax] | [Category Concept] | [Arts and Crafts of Tcl-Tk Programming] ]]