Is it possible to assign to a $b ´s value and to b $a ´s value without using a third variable? Is there a function to do so?
Why not just:
let a b @= $b $a
Which, by the way, also allows:
let a b c = 1 ;#this sets a b and c to 1 let a b c = 1 + 4 ;#"=" uses expr to process the value to assign let a b c += 1 ;#computed assignments are allowed, +-*/&| supported let a b c := info commands ;#uses eval to process right side let a b c @= 1 2 3 ;#instead of assigning the list {1 2 3} to a b and c, ;#it instead assigns the elements in order, resulting ;#in a getting the value 1, b getting 2 and so on. let a b c @:= info commands ;#uses eval to get result and uses @= for assignment let a ++ ;#incr and let a -- ;#decr are supported.
My suggestion will swap a-b and vice versa:
foreach {a b} [list $b $a] {}
Although proc let has many other features of course.
proc let { args } { if { [llength $args ] == 2 } { if [string equal [ lindex $args 1 ] "++" ] { set result [ uplevel incr [ lindex $args 0 ] ] } elseif [string equal [ lindex $args 1 ] "--" ] { set result [ uplevel incr [ lindex $args 0 ] -1 ] } else { set result [ uplevel set "$args" ] } } else { regexp {([^=:+\-*/&|@]*)([:+\-*/&|@]?)([@]*)=(.*)} $args -> vars op optional rest if ![ info exists op ] { return -code error -errorcode 1 "no valid assignment operator in $args" } switch -- $op { : { if [llength [info commands [lindex $rest 0]]] { set result [uplevel $rest] } else { set result $rest ;# this should always work... } if { "$optional" == "@" } { set max [ llength $result ] foreach var $vars res $result { uplevel 1 [ list set $var $res ] } } else { foreach var $vars { set result [ uplevel [list set $var $result] ] } } } @ { if { "$optional" == ":" } { set rest [uplevel $rest] } set max [ llength $rest ] if { $max == 1 } { eval set rest $rest set max [ llength $rest ] } foreach var $vars res $rest { set result [ uplevel 1 [ list set $var $res ]] } } + - - - * - / - & - | { foreach var $vars { set result [ uplevel set $var \[ expr \$$var $op ( $rest ) \] ] } } = - default { if { [ catch { set result [ uplevel expr $rest ] } ] } { set result $rest ;# this should always work... } foreach var $vars { set result [ uplevel [list set $var $result] ] } } } } return $result }
RS The code fragment (appears twice above)
set i 0 foreach var $vars { uplevel set $var [ lindex $result $i ] incr i }
seems like it can be replaced by
foreach var $vars res $result { uplevel 1 [list set $var $res] }
- if foreach can do a job once, it might as well do it twice ;-) A variable saved, and possibly safer with the list wrapper...
Larry Smith I'd clean forgotten that feature. Yes, it's much more elegant that way. The above code has been corrected.
RFox See Larry McVoy's L language? extension? to Tcl from Tcl 2006:
http://www.tcl.tk/community/tcl2006/papers/Larry_McVoy/l.pdf