[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 [wish]es 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... ---- [AMG]: While I appreciate this demonstration of Tcl's power to modify itself, I think it's ill advised to make this particular change. There's no way to distinguish between $x having been set to a single value that happened to be a list versus having been set via multiple arguments. You may say that there's no need to distinguish, since these two operations are defined to be equivalent. But what if the multiple arguments came as the result of [{*}] or its predecessor [[[eval]]]? And what if the "multiple" arguments happened to be only one argument after expansion? Now you're in trouble, if this first and only argument is not a well-formed list (e.g. has an unmatched open brace) or is a well-formed list with [[[llength]]]!=1? Just use ordinary [[[set]]] with [[[list]]], and avoid all the headaches. <> Command | Example