Skip to content
VLSI Mentor

Tcl Part I · Module 6 · Lists

lassign: Unpacking a List Into Variables

This closes the module with a small command that improves a lot of code. Pulling fields out of a record with numbered index calls works, and it leaves a reader counting positions to understand what each value is — and it breaks silently everywhere at once if a field is ever inserted. One line replaces the lot, names every field where a reader can see it, and hands back anything left over. It also has one behaviour worth knowing before you rely on it, which differs from the similar-looking command you met in the strings module.

Foundation10 min readTclPart IListsUnpackingReadability

Part I · Module 6 · Chapter 6.14 · lassign

1. The Command

Azvya Education Pvt. Ltd.VLSI Mentor
basic.tcl
lassign {alpha beta gamma} first second third

puts "first=$first second=$second third=$third"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
first=alpha second=beta third=gamma

A list, then variable names — no $, as with set, lappend and lset. Each element goes into the corresponding variable.

2. What It Replaces

Azvya Education Pvt. Ltd.VLSI Mentor
before.tcl
set row {clk 1 input}

set name      [lindex $row 0]
set width     [lindex $row 1]
set direction [lindex $row 2]

puts "$name $width $direction"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
clk 1 input
Azvya Education Pvt. Ltd.VLSI Mentor
after.tcl
set row {clk 1 input}

lassign $row name width direction

puts "$name $width $direction"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
clk 1 input

Three lines become one, and that is the smaller benefit.

The larger one is that the field names now appear once, in order, where a reader can see the record's shape. The lindex version makes you read three lines and match numbers to names.

3. Missing Elements Become Empty

Azvya Education Pvt. Ltd.VLSI Mentor
missing.tcl
lassign {one two} a b c

puts "a=<$a> b=<$b> c=<$c>"
puts "c exists: [info exists c]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
a=<one> b=<two> c=<>
c exists: 1

There were two elements and three variables. The third was set to the empty string — and it does exist afterwards.

That is different from scan, which leaves unmatched variables unset:

CommandA field that was not supplied
lassignset to the empty string
scanleft unset — reading it is an error

So the defensive check is different too. With scan you check the returned count; with lassign you check the list length before unpacking:

Azvya Education Pvt. Ltd.VLSI Mentor
guard.tcl
set row {clk 1}

if {[llength $row] != 3} {
    puts "expected 3 fields, got [llength $row]"
} else {
    lassign $row name width direction
    puts "$name $width $direction"
}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
expected 3 fields, got 2

Without that check you get an empty direction and no indication anything was wrong — the same silent-empty-value problem as Chapter 6.4 §3.

4. Extra Elements Are Returned

Azvya Education Pvt. Ltd.VLSI Mentor
leftover.tcl
set rest [lassign {1 2 3 4 5} first second]

puts "first=$first second=$second"
puts "rest=<$rest> ([llength $rest] elements)"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
first=1 second=2
rest=<3 4 5> (3 elements)

lassign returns whatever it did not use.

That gives a clean way to take the head of a list and keep the tail:

Azvya Education Pvt. Ltd.VLSI Mentor
head-tail.tcl
set queue {alpha beta gamma delta}

set queue [lassign $queue next]

puts "took:      $next"
puts "remaining: $queue ([llength $queue] left)"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
took:      alpha
remaining: beta gamma delta (3 left)

One line removes the first element and gives it to you — the list equivalent of popping from a queue. Compare with Chapter 6.7 §3's lreplace approach, which needs two statements.

5. Discarding Fields

There is no placeholder syntax, so the convention is a variable you ignore:

Azvya Education Pvt. Ltd.VLSI Mentor
discard.tcl
set row {clk 1 input "the main clock"}

lassign $row name - - description

puts "name=$name description=$description"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
name=clk description=the main clock

- is an ordinary variable name here — it genuinely gets set, and nothing stops you reading it. It simply reads as "not interested", and _ is equally common.

6. Where You Will Use It

Walking a table — the shape from Chapter 6.11 §4:

Azvya Education Pvt. Ltd.VLSI Mentor
table.tcl
set table {{clk 1 input} {reset 1 input} {payload 64 output}}

foreach row $table {
    lassign $row name width direction
    puts [format "  %-10s %4d  %s" $name $width $direction]
}
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
  clk           1  input
  reset         1  input
  payload      64  output

After a split — the registry's own example, joining this module to Chapter 5.13:

Azvya Education Pvt. Ltd.VLSI Mentor
after-split.tcl
set line "widget,42,3.5"

lassign [split $line ","] name count value

puts "name=$name count=$count value=$value"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
name=widget count=42 value=3.5

That one line is the whole point of the chapter: text came in, became a list, and its fields now have names.

7. Common Mistakes

Writing lassign $row $name. The targets are names, not values.

Assuming a missing field is unset. It is an empty string. §3.

Forgetting to check the length first. §3.

Confusing it with scan. Different missing-field behaviour and different checks. §3.

Ignoring the return value when you wanted the tail. §4.

Using it on a record with many fields. Eight names on one line is as unreadable as eight lindex calls. That is the signal for a dictionary — Chapter 6.11 §7.

8. Exercises

Exercise 1 — unpack three. Unpack {red green blue} into three named variables and print them.

Exercise 2 — before and after. Write a record unpack with three lindex calls, then with lassign. Then insert a new field at the front of the record and say how many lines each version needs changing.

Exercise 3 — too few. Unpack a two-element list into three variables. Print all three in angle brackets and check whether the third exists. Then add the guard that catches it.

Exercise 4 — the leftovers. Take the first two elements of a six-element list and print how many remain.

Exercise 5 — pop. Write the one-line "take the first element and keep the rest" idiom, and run it twice on the same list.

Exercise 6 — after a split. Parse "clk,1,input" into three named variables in two lines total.

9. What You Can Now Do

That closes Module 6. Across fourteen chapters you have Tcl's central data structure:

  • what a list actually is, and why not every string is one
  • building one correctly, and the corruption that follows from not doing so
  • counting, indexing, slicing
  • growing, inserting, replacing, deleting, and updating in place
  • searching by value, pattern or column — and the two traps in doing so
  • sorting by any key, and the default that is wrong for numbers
  • nesting lists into tables, and when to stop
  • combining versus nesting
  • expanding a list into arguments
  • and unpacking one into named variables

The thread running through it is the one from Chapter 6.1: a list is a string read by list rules. Everything else follows — the automatic quoting, the free composition with text commands, and the ways a careless text operation can change an element count.

Module 7 is Dictionaries and Arrays, which Chapter 6.11 §7 has already made the case for: once records have several fields, or fields that may change, naming them beats numbering them.

10. Remember

  • lassign list name ... unpacks elements into variables. Names, not values.
  • It replaces a chain of numbered lindex calls and names the record's fields in one visible place.
  • Numbered access encodes the layout everywhere you use it — that is the real argument, not line count.
  • Missing elements become the empty string, and the variable does exist.
  • That differs from scan, which leaves them unset — so check llength before unpacking, not info exists after.
  • Extra elements are returned, which gives the one-line "pop the head" idiom.
  • Use - or _ for fields you do not want. There is no real placeholder.
  • Many fields means you want a dictionary — Module 7.

Where this fits

Part of the Tcl curriculum.