Skip to content
VLSI Mentor

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

expr: Arithmetic Is a Command, Not Syntax

Module 2 claimed that Tcl has almost no syntax and that nearly everything is a command. Arithmetic is where that claim becomes concrete and slightly startling. Plus and minus are not operators in Tcl — the language does not know what they are. There is a command called expr which understands a small expression language of its own, and arithmetic happens inside it. This chapter shows what follows from that, starting with a line that surprises everybody the first time they type it.

Foundation13 min readTclPart IValuesexprArithmetic

Part I · Module 3 · Chapter 3.7 · expr: Arithmetic Is a Command, Not Syntax

1. The Surprise

Type this and predict the output:

Azvya Education Pvt. Ltd.VLSI Mentor
surprise.tcl
set x 1+1
puts $x

Most people expect 2.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
1+1

Three characters, stored exactly as written. You can check:

Azvya Education Pvt. Ltd.VLSI Mentor
three-chars.tcl
set x 1+1
puts "stored: $x"
puts "length: [string length $x]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
stored: 1+1
length: 3

Nothing went wrong. set was given a name and a word, and it stored the word. The word happened to contain a plus sign, which is an ordinary character.

2. Tcl Does Not Do Arithmetic

That example is not a quirk to work around. It is the correct behaviour of a language in which + means nothing.

Chapter 2.1 said Tcl's grammar is one rule: a command and its words. There is no rule about operators, no precedence table in the parser, no arithmetic in the language at all.

So where does arithmetic come from? A command.

Azvya Education Pvt. Ltd.VLSI Mentor
expr.tcl
puts [expr {1 + 1}]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
2

expr is an ordinary command. It takes an expression, works it out, and returns the answer. The brackets are command substitution — Chapter 2.5 — so the result becomes a word in the puts command.

3. Proof: + Is Not a Command Either

If + is not syntax, is it perhaps a command? No:

Azvya Education Pvt. Ltd.VLSI Mentor
not-a-command.tcl
puts [catch {+ 1 1} m]
puts $m
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
1
invalid command name "+"

There is no command called +.

So the plus sign is neither Tcl syntax nor a Tcl command. It is part of a small language that expr understands and nothing else does. Tcl hands expr some text; expr parses that text with its own rules.

That is the whole mental model, and it explains everything else in this chapter and the next.

4. Using the Result

expr returns a value like any command, so you store or use it the usual ways:

Azvya Education Pvt. Ltd.VLSI Mentor
using.tcl
set total [expr {4 * 5}]
puts "total = $total"

set width 8
puts "doubled = [expr {$width * 2}]"
puts "nested  = [expr {[expr {2 + 3}] * 10}]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
total = 20
doubled = 16
nested  = 50

The nested line works but is pointless — expr {(2 + 3) * 10} says the same thing. It is here only to show that expr is genuinely an ordinary command that can appear inside another command's words.

5. Always Brace the Expression

Every example on this page writes the expression inside braces:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
expr {$width * 2}      ;# do this
expr $width * 2        ;# not this

Brace the expression, always. It is correct, it is faster, and the next chapter — Chapter 3.8 — shows exactly what the unbraced form does wrong and why it is worth a chapter of its own.

For now treat it as a rule with a reason coming.

6. The Bareword Error

A mistake worth meeting now, because Tcl's message is unusually helpful:

Azvya Education Pvt. Ltd.VLSI Mentor
bareword.tcl
set passed 7
puts [expr {passed + 1}]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
invalid bareword "passed"
in expression "passed + 1";
should be "$passed" or "{passed}" or "passed(...)" or ...

Inside an expression, a bare name is not a variable. expr has its own rules, and in those rules passed on its own is meaningless — it is not a number and not a known function.

Tcl spotted the likely cause and told you the fix: write $passed. Add the dollar sign and it works:

Azvya Education Pvt. Ltd.VLSI Mentor
bareword-fixed.tcl
set passed 7
puts [expr {$passed + 1}]
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
8

This is a common first-week error, especially for people arriving from languages where a bare identifier in an expression means a variable.

7. The Operators, Briefly

expr understands roughly what you would expect:

Azvya Education Pvt. Ltd.VLSI Mentor
operators.tcl
puts "add:      [expr {7 + 3}]"
puts "subtract: [expr {7 - 3}]"
puts "multiply: [expr {7 * 3}]"
puts "divide:   [expr {7 / 3}]"
puts "remainder:[expr {7 % 3}]"
puts "power:    [expr {7 ** 3}]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
add:      10
subtract: 4
multiply: 21
divide:   2
remainder:1
power:    343

Look at the division line. 7 / 3 is 2, not 2.333. That is not a mistake and it is the subject of Chapter 3.10.

Comparison, logical and bitwise operators also live in expr, along with precedence rules and a set of maths functions. Module 4 is entirely about them, so this chapter stops at naming them.

8. Maths Functions

A small sample, since they come up alongside arithmetic:

Azvya Education Pvt. Ltd.VLSI Mentor
functions.tcl
puts "abs:   [expr {abs(-7)}]"
puts "round: [expr {round(2.6)}]"
puts "max:   [expr {max(3, 9, 4)}]"
puts "sqrt:  [expr {sqrt(16)}]"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
abs:   7
round: 3
max:   9
sqrt:  4.0

Note sqrt(16) is 4.0 and not 4 — a function that works in real numbers returns one. This matters when you print a result or compare it, and Chapter 3.10 covers why.

These are functions in expr's language, not Tcl commands. abs -7 on its own fails the same way + 1 1 did.

9. Common Mistakes

Expecting set x 1+1 to calculate. §1. It stores three characters.

Writing a bare variable name inside an expression. §6. Use $name.

Leaving the expression unbraced. §5, and Chapter 3.8 shows the damage.

Calling a maths function as a command. sqrt 16 is not a command; expr {sqrt(16)} is.

Expecting / to give a decimal. Chapter 3.10.

Using expr where you do not need it. incr adds one to a counter without an expression — Chapter 3.9 — and comparisons inside if already evaluate as expressions, which Module 8 covers.

10. Exercises

Exercise 1 — reproduce the surprise. Run set x 1+1 and print both the value and its length. Then produce 2 in the same script.

Exercise 2 — prove + is not a command. Run + 1 1 inside catch and print the message. Then do the same for sqrt 16. What do the two errors have in common?

Exercise 3 — meet the bareword error. Write expr {total * 2} with total set to 5. Read the message and apply the fix it suggests.

Exercise 4 — store and reuse. Set width to 12. Compute the area of a square of that width, store it in area, and print both. Use one expr only.

Exercise 5 — predict six. Before running, write down the answer for each:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts [expr {9 / 2}]
puts [expr {9 % 2}]
puts [expr {2 ** 10}]
puts [expr {abs(-3.5)}]
puts [expr {round(0.5)}]
puts [expr {sqrt(9)}]

Two of these may not match your first guess. Work out why.

Exercise 6 — explain it. A colleague asks why Tcl "makes you write expr". Answer in two sentences using §2 and §3, without saying that Tcl is old.

11. Remember

  • +, -, * and / are not Tcl syntax and not Tcl commands. + 1 1 fails with invalid command name.
  • Arithmetic belongs to expr, an ordinary command with its own small expression language.
  • set x 1+1 stores three characters. Nothing went wrong.
  • expr returns a value, so use it with command substitution: set total [expr {...}].
  • Always brace the expression. Chapter 3.8 explains why.
  • A bare name inside an expression is an error — write $name. Tcl's message tells you so.
  • Maths functions are part of expr's language, not commands.
  • 7 / 3 is 2. Chapter 3.10.

Next: the one rule that makes expr both correct and fast, and the damage done without it.

Where this fits

Part of the Tcl curriculum.