Tcl Part I · Module 3 · Values, Variables, and Expressions
Truth in Tcl: What Counts as True and False
Tcl has no boolean type, because values do not carry types at all. What it has instead is a set of words and numbers that count as true or false when something reads a value as a truth value. The list is short and worth knowing exactly. The more important half of this chapter is what happens to everything not on the list, because the answer is not what you will expect if you have written Python or JavaScript — and the Tcl behaviour is genuinely better, for a reason worth understanding.
Foundation11 min readTclPart IValuesBooleansConditions
Part I · Module 3 · Chapter 3.6 · Truth in Tcl: What Counts as True and False
1. There Is No Boolean Type
Chapter 3.1 said values carry text and commands decide what it means. Truth is one such reading.
So there is no true object and no boolean variable. There is a set of values that, when something reads them as a truth value, count as true or false.
2. The Accepted Words
foreach v {1 0 yes no true false on off} {
puts [format "%-6s -> %s" $v [expr {$v ? 1 : 0}]]
}1 -> 1
0 -> 0
yes -> 1
no -> 0
true -> 1
false -> 0
on -> 1
off -> 0Four pairs: 1/0, yes/no, true/false, on/off.
They are case-insensitive:
foreach v {YES Off TRUE} {
puts "$v -> [expr {$v ? 1 : 0}]"
}YES -> 1
Off -> 0
TRUE -> 13. Numbers
Any number works, and the rule is the familiar one — zero is false, anything else is true:
foreach v {2 -1 0.0 0.5} {
puts "$v -> [expr {$v ? 1 : 0}]"
}2 -> 1
-1 -> 1
0.0 -> 0
0.5 -> 1Note -1 is true. "True" does not mean "positive"; it means "not zero".
And 0.0 is false, so a floating-point zero behaves like an integer zero. That is worth knowing because a computed value that lands exactly on zero will take the false branch, while one that lands on 0.0000001 will not.
4. Everything Else Is an Error
Here is where Tcl differs from the languages you are most likely coming from:
puts [expr {"hello" ? 1 : 0}]expected boolean value but got "hello"Not false. An error.
And the one that catches Python programmers hardest:
puts [expr {"" ? 1 : 0}]expected boolean value but got ""The empty string is also an error.
| Language | "" in a condition | "hello" in a condition |
|---|---|---|
| Python | false | true |
| Tcl | error | error |
If you write Tcl expecting Python's rules, you will write conditions that look sensible and stop the script.
5. Why the Error Is the Right Behaviour
It is tempting to see this as Tcl being unhelpful. It is the opposite.
Consider a condition that tests a value you misspelled, or a field that failed to parse and came back empty. Under Python's rules the condition quietly evaluates to false and the script takes the wrong branch — silently, with no indication anything went wrong. You find out later, from the output, if at all.
Tcl stops and tells you the value was not a truth value. A bad condition becomes a loud failure rather than a silent wrong answer.
This is the same design choice as reading a missing variable being an error — Chapter 3.2 §8. Tcl prefers to fail where the problem is.
6. Asking Without Risking the Error
If a value might not be a truth value, test it first — the same discipline as Chapter 3.5:
foreach v {yes 1 maybe ""} {
puts [format "%-6s -> %s" "<$v>" [string is boolean -strict $v]]
}<yes> -> 1
<1> -> 1
<maybe> -> 0
<> -> 0string is boolean -strict returns 1 only for values Tcl would accept. And as in Chapter 3.5, write -strict — without it the empty string passes.
A guard for a configuration value that should be a yes/no flag:
set flag "maybe"
if {[string is boolean -strict $flag]} {
puts "verbose mode: [expr {$flag ? "on" : "off"}]"
} else {
puts "not a yes/no value: $flag"
}not a yes/no value: maybe7. Where Truth Values Come From
Comparisons produce them, which is how conditions normally get written:
set count 3
puts "count > 0 -> [expr {$count > 0}]"
puts "count == 10 -> [expr {$count == 10}]"count > 0 -> 1
count == 10 -> 0Comparisons return 1 or 0. That is why you rarely write yes or on in a condition yourself — you write a comparison, and it produces a value already on the accepted list.
The words matter most for configuration: a flag read from a file or supplied by a user is far more likely to be the text yes than the number 1, and Tcl accepting both is what makes that convenient.
8. Common Mistakes
Expecting an empty string to be false. It is an error. §4.
Expecting a non-empty string to be true. Also an error. §4.
Testing a value that might be text without checking. Use string is boolean -strict first. §6.
Omitting -strict. Same trap as Chapter 3.5 — the empty string passes.
Assuming only 1 and 0 work. Four pairs of words work, case-insensitively, plus any number. §2 and §3.
Thinking -1 is false. Not zero means true. §3.
9. Exercises
Exercise 1 — the full set. Write a loop that prints the truth value of all eight accepted words plus three capitalised variants. Confirm the pairs behave as you expect.
Exercise 2 — meet the error. Evaluate a condition on the value hello, then on the empty string. Read both messages. Write one sentence saying why this is better than silently returning false.
Exercise 3 — the Python habit. This line looks reasonable and is wrong in Tcl:
set name ""
puts [expr {$name ? "has a name" : "no name"}]Run it, then rewrite it so it works, testing explicitly for an empty value.
Exercise 4 — numbers. Predict the truth value of 0, 0.0, -1, 0.0001 and 2. Then check.
Exercise 5 — a safe flag reader. Write a script that takes a variable flag and prints enabled, disabled, or invalid setting: <value>. Test it with yes, off, 1, maybe and "".
Exercise 6 — where do truth values come from? Without using any of the eight words, write three conditions that produce 1 and three that produce 0.
10. Remember
- There is no boolean type. Truth is a reading of a value, like arithmetic is.
- Four pairs are accepted:
1/0,yes/no,true/false,on/off— case-insensitively. - Any number works: zero is false, anything else is true, including negatives.
0.0is false. - Everything else is an error, including the empty string. Not false — an error.
- That is deliberate and better. A bad condition fails loudly instead of silently taking the wrong branch.
- Do not rely on truthiness. Test explicitly for what you mean, such as
$name ne "". string is boolean -strictasks safely — and-strictis required, as always.- Comparisons return
1or0, which is where most conditions get their values.
Next: the command that does arithmetic, and why Tcl needs one at all.
Where this fits
Part of the Tcl curriculum.
