Updated 2017-06-08 09:36:17 by dbohdan

arrexpr edit

dbohdan 2015-02-20: This little hack implements a piece of syntax resembling the expr shorthand from Jim Tcl in Tcl 8.x: $(...). It does so by tracing array reads from the array with the name {} (an empty string).

A kind of double substitution is sadly unavoidable here. Basically, subst is performed on an array index before it is passed to the proc tracing it. This, together with the very syntax used for array indexing, means that you have to manually escape $, g and () with a backslash in your expressions. This is rather error prone, which is why the author would recommend against using arrexpr for anything but amusement.

Code

namespace eval ::arrexpr {
    namespace export *
    upvar #0 {} {}
    set () {}
    trace add variable {} {array read write unset} ::arrexpr::tracer
}

proc ::arrexpr::tracer {name index op} {
    if {$name eq ""} {
        global $name
        switch -exact -- $op {
            read {
                array unset $name *
                set ($index) [uplevel 1 [list expr $index]]
            }
            write {
                error "not writable"
            }
        }
    }
}

proc ::arrexpr::use {} {
    uplevel 1 {
        upvar #0 {} {}
    }
}

Use examples

source arrexpr.tcl

puts $(2 + 2)

proc vector-length {a b} {
    ::arrexpr::use
    return $(sqrt\($a * $a + $b * $b\))
}
puts [vector-length 1 1]

puts $("hello")

# Double substitution. :-(
set a 1
set b a
puts $($$b) ;# prints "1"

set value 5
puts $(\$value > 0 ? "positive" : "zero or negative")