Version 19 of lassign

Updated 2005-03-21 15:43:16

As from 8.5, lassign is in the Tcl core - see Changes in Tcl/Tk 8.5 and TIP 57 [L1 ].


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 varNames? 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.

official reference

Example usage:

    lassign {value1 value2} variable1 variable2

in place of

    set variable1 value1
    set variable2 value2
TIP 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] == ""} {
    proc lassign {values args} {
        uplevel 1 [list foreach $args $values break]
        lrange $values [llength $args] end
    }
 }

Category Command