Version 10 of multi-argument set

Updated 2005-12-14 19:58:33

Richard Suchenwirth 2005-12-12 - In the Tcl chatroom, CMcC said:

 You know, in retrospect, I think [set x a b c] should be equivalent to [set x [list a b c]]

Well, Tcl is where wishes come true :) Here's my experimental code that overloads set, and seems to work fine, as far as I've tested. I had to reuse the _var name for upvar, so the error message comes right if the variable doesn't exist yet:

 rename set _set
 proc set {_var args} {
    upvar 1 $_var $_var
    _set ll [llength [info level 0]]
    if {$ll==3} {
        _set $_var [lindex $args 0]
    } elseif {$ll>3} {_set $_var $args}
    _set $_var
 }

Lars H: Ehh... Why this insanely complicated solution? The user-supplied name for a local variable is just asking for trouble -- consider what happens for [set ll]!! The straightforward solution is rather:

 proc set {varname args} {
    upvar 1 $varname var
    if {[llength $args] == 0} then {
       return $var
    } elseif {[llength $args] == 1} then {
       _set var [lindex $args 0]
    } else {
       _set var $args
    }
 }

RS: It is to avoid the misleading error message below - but I agree that variable ll opens a vulnerability, so your code is safer.

 % set foo
 can't read "var": no such variable

Ingemar H: The above small problem is easily solved by this:

    if {[llength $args] == 0} then {
      if {[info exists var]} {
        return $var
      } else {
        _set $varname
      }

The distinction between $ll==3 and $ll>3 is necessary so this frequent case comes right:

 set something {}

Testing:

 % source myset.tcl
 % set foo
 can't read "foo": no such variable
 % set foo 1
 1
 % set foo
 1
 % set bar 2 3 4
 2 3 4
 % set bar
 2 3 4
 % set grill {{}}
 {}
 % set grill
 {}
 % set nix {}
 % set nix
 %

So far it looks as expected. But bytecode compilation may lose performance if a fundamental like set is pulled from under its feet...


Category Command Category Example