Version 7 of C-like syntax for numbers

Updated 2007-02-05 10:46:02 by NEM

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.

slebetman: Should this really be in Category Mathematics? Since this has very little to do with mathematics.

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 aliases 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
 }

See also: infix, Gadgets, Radical Language Modification and Let unknown know


Category Syntax , Category Concept , Arts and Crafts of Tcl-Tk Programming