Skip to content
VLSI Mentor

Tcl Part I · Module 6 · Lists

lindex, and Counting From the End

Reading one element out of a list uses the same index vocabulary you already learned for strings, so most of this chapter will feel familiar: positions start at zero, end counts from the right, and simple arithmetic works inside the position. Two things are new. Out-of-range behaviour is worth stating plainly because it is forgiving in a way that hides mistakes, and there is a multi-index form that reaches straight into a nested list without pulling the intermediate levels out first.

Foundation11 min readTclPart IListsIndexing

Part I · Module 6 · Chapter 6.4 · lindex

1. Positions Start at Zero

Azvya Education Pvt. Ltd.VLSI Mentor
basic.tcl
set fields {alpha beta gamma delta}

puts "0 -> [lindex $fields 0]"
puts "2 -> [lindex $fields 2]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
0 -> alpha
2 -> gamma

Same as Chapter 5.3, except the unit is an element rather than a character.

2. The Same Index Vocabulary

Everything you learned for string indexing applies:

Azvya Education Pvt. Ltd.VLSI Mentor
end.tcl
set fields {alpha beta gamma delta}

puts "end    -> [lindex $fields end]"
puts "end-1  -> [lindex $fields end-1]"

set i 2
puts "i-1    -> [lindex $fields $i-1]"
puts "i+1    -> [lindex $fields $i+1]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
end    -> delta
end-1  -> gamma
i-1    -> beta
i+1    -> delta

end and end-N are index keywords, and simple arithmetic works inside the position with no expr.

Being able to write end means you never compute [expr {[llength $l] - 1}], which is where off-by-one errors come from.

3. Out of Range Is Empty

Azvya Education Pvt. Ltd.VLSI Mentor
out-of-range.tcl
set fields {alpha beta}

puts "99 -> <[lindex $fields 99]>"
puts "-1 -> <[lindex $fields -1]>"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
99 -> <>
-1 -> <>

No error. An index past either end gives an empty string.

4. No Index at All

Azvya Education Pvt. Ltd.VLSI Mentor
no-index.tcl
set fields {alpha beta gamma}

puts [lindex $fields]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
alpha beta gamma

Called with no index, lindex returns the whole list unchanged.

That sounds useless and occasionally is not — it means a loop that peels one index at a time terminates sensibly rather than erroring. Mostly it is worth knowing so that an index coming from a variable that happens to be empty does not surprise you.

5. Reaching Into Nested Lists

Several indices drill down one level each:

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

puts "whole row 2  -> [lindex $table 2]"
puts "row 2, col 0 -> [lindex $table 2 0]"
puts "row 2, col 1 -> [lindex $table 2 1]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
whole row 2  -> payload 64
row 2, col 0 -> payload
row 2, col 1 -> 64

lindex $table 2 0 means "element 2 of the list, then element 0 of that". It is the same as nesting two calls:

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

puts [lindex [lindex $table 2] 0]
puts [lindex $table 2 0]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
payload
payload

The multi-index form reads better and is the idiomatic one. Chapter 6.11 uses it throughout.

6. Common Shapes

First and last:

Azvya Education Pvt. Ltd.VLSI Mentor
first-last.tcl
set queue {alpha beta gamma}

puts "first: [lindex $queue 0]"
puts "last:  [lindex $queue end]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
first: alpha
last:  gamma

Pulling named fields out of a record:

Azvya Education Pvt. Ltd.VLSI Mentor
record.tcl
set row [split "clk,1,input" ","]

puts "name:      [lindex $row 0]"
puts "width:     [lindex $row 1]"
puts "direction: [lindex $row 2]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
name:      clk
width:     1
direction: input

That works and there is a better way to write it. Three lindex calls with bare numbers tell a reader nothing about what the columns mean, and renumbering them when a column is added is error-prone. Chapter 6.14 replaces all three lines with one.

7. It Does Not Modify the List

Azvya Education Pvt. Ltd.VLSI Mentor
read-only.tcl
set l {a b c}

lindex $l 0
puts "unchanged: $l"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
unchanged: a b c

lindex reads. To change an element you want Chapter 6.8, which is the one list command that writes to the variable directly.

8. Common Mistakes

Indexing without checking the length. §3. The main one.

Computing the last index with llength. Use end. §2.

Expecting an error for an out-of-range index. You get "". §3.

Using lindex on a string expecting characters. lindex "hello" 0 is hello, because that text is a one-element list. For characters use string index — Chapter 5.3.

Nesting lindex calls by hand. The multi-index form is clearer. §5.

A chain of numbered lindex calls for a record. Use lassign. §6.

9. Exercises

Exercise 1 — positions. For {red green blue yellow}, print elements 0, 2, end and end-2.

Exercise 2 — out of range. Print element 10 of a three-element list between angle brackets. Then write the check that would have caught it.

Exercise 3 — the string trap. Predict lindex "hello" 0 and string index "hello" 0. Run both and explain why they differ.

Exercise 4 — nested. For {{a 1} {b 2} {c 3}}, pull out the value 2 using the multi-index form, then again using two nested calls.

Exercise 5 — index arithmetic. With set i 1, print the element before and after position i in a four-element list, without using expr.

Exercise 6 — the record smell. Take the three-lindex record example from §6 and say what breaks if a column is inserted at the front. Then look ahead to Chapter 6.14 and say how it helps.

10. Remember

  • lindex list index reads one element. Positions start at 0.
  • Same vocabulary as string indexing: end, end-N, and arithmetic like $i-1 inside the position.
  • Out of range returns an empty string, never an error — at either end.
  • So check llength first when the list came from outside.
  • With no index it returns the whole list.
  • Several indices drill into nested lists: lindex $t 2 0.
  • It never modifies the list. lset is for writing.
  • lindex "hello" 0 is hello, because that is a one-element list.

Next: taking several elements at once.

Where this fits

Part of the Tcl curriculum.