As from 8.5, [lassign] is in the Tcl core - see [Changes in Tcl/Tk 8.5] and TIP 57 [http://purl.org/tcl/tip/57.html]. ---- ''[escargo] 4 Feb 2004'' - The example in the TIP given above is as follows: lassign $listValue $varName ?$varName ...? Is there a particular reason for the $ in front of the '''varName'''s? It seems like the pattern should really be lassign $listValue varName ?varName ...? There are a variety of metasyntaxes out there for trying to describe a synopsis of a command. If I try to use the same one as in the man pages, I get '''lassign''' ''list'' ''varName'' ?''varName'' ...? ** Documentation ** Some contexts (TIPs are a notable example) do not offer enough formatting variations to support that look, so leading $ tends to take the place of italic formatting. Then sometimes those descriptions in TIPs get cut/pasted here without modification. More than you want to know? [DKF]: No, they're just due to a limitation in the TIP format; nothing more. Sometime I'll support doing command specs better. ---- [TclX] has supplied lassign since the early [[or mid-?]] '90s. [http://www.tcl.tk/man/tcl/TclCmd/lassign.htm%|%official reference]: Example usage: lassign {value1 value2} variable1 variable2 in place of set variable1 value1 set variable2 value2 [TIP] [http://purl.org/tcl/tip/57.html%|%57]: proposed making the [TclX] `lassign` command a built-in Tcl command ** Description ** ---- Actually, note that lassign takes a list and assigns each element to a variable. Thus, while the above is true, the list of values can have dozens of elements. For example: lassign [list 1 2 3 4 5 6 7] variable1 variable2 puts $variable1 1 puts $variable2 2 `lassign` assigns values from a [list] to the specified variables, and The more variables you supply, the more single values are assigned. ====== ---- ''Does lassign in [Tcl] 8.5 differ in any way from TclX's version?'' % They do not differ in any script-visible way. You call them with the same syntax. Same arguments to both implies same results from both. In Tcl prior to 8.5, `[foreach]` was used to achieve the functionality of The internal implementation is not the same; the new [[lassign]] in Tcl 8.5 makes use of the bytecode compiler. ====== [DKF]: The new implementation is also much more heavily tested. I've a bit of experience with being paranoiac about tests these days... :^/ ---- [DKF] cleverly points out that lassign makes a Perlish [[shift]] this easy: proc shift {} { global argv set argv [lassign $argv v] return $v } On the other hand, [Hemang Lavana] observes that TclXers already have "[lvarpop] ::argv", an exact synonym for "shift". [KPV] - For those who want to use [[lassign]] before Tcl 8.5, and without getting [TclX], here's a tcl-only version of lassign: if {[info procs lassign] == ""} { set vlen [llength $values] set alen [llength $args] for {set i $vlen} {$i < $alen} {incr i} { ;# Make lists equal length } uplevel 1 [list foreach $args $values break] return [lrange $values $alen end] } } } [jcw]: Couldn't resist rewriting in a style I prefer. Chaq'un son gout - a [jcw] - Couldn't resist rewriting in a style I prefer. Chaq'un son gout - a matter of taste - of course: ====== if {[info procs lassign] == ""} { while {[llength $values] < [llength $args]} { lappend values {} } uplevel 1 [list foreach $args $values break] lrange $values [llength $args] end } } } [KPV]: But from an efficiency point of view, you're calling `[llength]` way too [KPV] - But from an efficiency point of view, you're calling '''llength''' way too many times--every iteration through the '''while''' loop does two unnecessary calls. How about this version--your style but more efficient: ====== if {[info procs lassign] == ""} { set alen [llength $args] set vlen [llength $values] while {[incr vlen] <= $alen} { lappend values {} } uplevel 1 [list foreach $args $values break] lrange $values $alen end } } } [jcw] interjects: Keith... are you sure `[llength]` is slower? (be sure to test ''Keith... are you sure llength is slower? (be sure to test inside a proc body) -[jcw]'' It must be my assembler/C background but I see those function calls, especially the one returning a constant value and wince. But you're correct, calling llength is no slower than accessing a variable. It guess the byte compiler is optimizing out the actual call. [KPV] [kpv] continues: It must be my assembler/C background but I see those function [DKF]: ''[llength]'' is indeed bytecoded. [DKF]: `[llength]` is indeed bytecoded. [sbron] - I see no reason to massage the values list at all. The foreach will do exactly the same thing even if the values list is shorter than the args list. I.e. this should be all that's needed: [sbron]: I see no reason to massage the values list at all. `[foreach]` will do if {[info procs lassign] eq ""} { proc lassign {values args} { uplevel 1 [list foreach $args $values break] lrange $values [llength $args] end } } This version does not work as described in the documentation for lassign for This version does not work as described in the documentation for lassign for this case: ====== % lassign [list] a b c % set a can't read "a": no such variable [sbron]: You are right, I just noticed that myself too. Improved version: ---- [CMcC]: I may be just exceptionally grumpy this morning 2005/11/14 but the behavior of supplying default empty values to extra variables means you can't distinguish between a trailing var with no matching value, and one with a value of {}. Needs an option, -greedy or something, to distinguish between the two cases. Oh, ''and'' it annoys me that [[lset]] is already taken, because [[lassign]] doesn't resonate well with [[set]]. ---- [Category Command]