Skip to content
VLSI Mentor

Tcl Part I · Module 3 · Values, Variables, and Expressions

unset, and Testing Whether a Variable Exists

Chapter 3.2 ended on an error: reading a variable that does not exist stops the script. That is good behaviour, because it catches typos, but it is not always what you want. Sometimes a value is genuinely optional and you need to supply a default. This chapter gives you the two commands that turn that error into a decision you control, plus the small surprise that removing a variable which is not there is itself an error unless you say otherwise.

Foundation11 min readTclPart IValuesVariablesDefensive Checks

Part I · Module 3 · Chapter 3.4 · unset, and Testing Whether a Variable Exists

1. The Problem

Azvya Education Pvt. Ltd.VLSI Mentor
problem.tcl
puts "limit is $limit"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
can't read "limit": no such variable

The script stops. For a typo that is exactly right — Chapter 3.2 §8 made the case.

But sometimes the variable is genuinely optional. Perhaps it is set by a configuration file that may not exist, or by an earlier step that may not have run. You need to ask rather than assume.

2. info exists

It returns 1 or 0:

Azvya Education Pvt. Ltd.VLSI Mentor
exists.tcl
puts "before:     [info exists limit]"

set limit 10
puts "after set:  [info exists limit]"

unset limit
puts "after unset: [info exists limit]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
before:     0
after set:  1
after unset: 0

Note what it does not do: it does not read the variable, so asking about a missing one is safe. That is the whole point — it is the one way to enquire without risking the error.

3. Existing and Empty Are Different

A variable can exist and hold nothing:

Azvya Education Pvt. Ltd.VLSI Mentor
empty-vs-missing.tcl
set found ""

puts "exists:  [info exists found]"
puts "is empty: [expr {$found eq \"\"}]"

unset found
puts "after unset, exists: [info exists found]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
exists:  1
is empty: 1
after unset, exists: 0

Three states, not two: not set, set but empty, and set to something. Collapsing the first two is a common source of bugs — "no value was supplied" and "the supplied value was blank" often need different handling.

4. The Default-Value Idiom

This is the pattern you will write most often:

Azvya Education Pvt. Ltd.VLSI Mentor
default.tcl
if {![info exists limit]} {
    set limit 10
}
puts "limit = $limit"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
limit = 10

And when the variable was already set, the default is skipped:

Azvya Education Pvt. Ltd.VLSI Mentor
default-kept.tcl
set limit 99

if {![info exists limit]} {
    set limit 10
}
puts "limit = $limit"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
limit = 99

Read it as "if it is not already set, set it". The ! negates, and if is Module 8 — you only need to know it runs the braced body when the condition is true.

5. unset Removes a Variable

Azvya Education Pvt. Ltd.VLSI Mentor
unset.tcl
set temp "working value"
puts "exists: [info exists temp]"

unset temp
puts "after unset: [info exists temp]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
exists: 1
after unset: 0

After unset, the variable is gone — not empty, gone. Reading it is an error again.

You can remove several at once:

Azvya Education Pvt. Ltd.VLSI Mentor
unset-many.tcl
set a 1
set b 2
set c 3

unset a b

puts "a exists: [info exists a]"
puts "c exists: [info exists c]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
a exists: 0
c exists: 1

6. Removing Something That Is Not There

Here is the surprise:

Azvya Education Pvt. Ltd.VLSI Mentor
unset-missing.tcl
unset nothere
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
can't unset "nothere": no such variable

An error. If you expected "remove it if it is there", Tcl does not assume that.

The flag that gives you that behaviour is -nocomplain:

Azvya Education Pvt. Ltd.VLSI Mentor
nocomplain.tcl
unset -nocomplain nothere
puts "survived"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
survived

Use -nocomplain when the variable is genuinely optional, and plain unset when its absence would mean something has gone wrong — the error is useful in that case.

7. What This Chapter Does Not Cover

Two related things, deliberately left for later so you do not get a half-answer now:

  • Array elements. info exists can ask about a single element of an array, which is a different question from whether the array exists. Module 7.
  • Scope. A variable can exist in one place and not another — inside a procedure you may not see a variable that exists outside it. info exists answers about the scope you are currently in. Module 11 deals with scope properly, and it is the most common reason info exists returns 0 for a variable that visibly exists elsewhere in the file.

8. Common Mistakes

Writing info exists $name. Asks about the wrong variable. §2.

Treating missing and empty as the same. Three states, not two. §3.

Plain unset on an optional variable. Errors. Use -nocomplain. §6.

Using info exists to work around a typo. If a variable "sometimes does not exist" and you cannot say why, the check is hiding the real problem rather than solving it.

Expecting it to see other scopes. §7.

9. Exercises

Exercise 1 — the three states. Write a script that prints, for the same variable name, the result of info exists when it is unset, when it is set to the empty string, and when it is set to hello.

Exercise 2 — the default idiom. Write the default-value pattern for a variable retries defaulting to 3. Run it twice: once with retries unset, and once with it already set to 7. Confirm both behave correctly.

Exercise 3 — cause both unset errors. Run unset nothere, read the error, then run unset -nocomplain nothere and confirm it is silent.

Exercise 4 — distinguish empty from missing. Write a procedure-free script that prints not supplied when a variable does not exist, supplied but blank when it exists and is empty, and the value otherwise. Test all three cases.

Exercise 5 — read the trap. Predict what this prints, then run it:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
set name limit
set limit 5
puts [info exists name]
puts [info exists $name]
puts [info exists nothing]

Explain the second line using §2.

10. Remember

  • Reading a missing variable is an error. That is useful default behaviour.
  • info exists name returns 1 or 0 and never reads the variable, so it is always safe to ask.
  • No dollar sign on the name — info exists $name asks about a different variable.
  • Existing and empty are different. Three states: not set, set but empty, set to something.
  • The default idiom is if {![info exists x]} { set x <default> }.
  • unset removes a variable, and takes several names at once.
  • Plain unset on a missing variable is an error; unset -nocomplain is the forgiving form.
  • Scope and array elements are later modules — they are the usual reason a surprising 0 comes back.

Next: when a value counts as a number, and how to find out before you rely on it.

Where this fits

Part of the Tcl curriculum.