Operators in Tcl
Learn arithmetic, comparison, logical, and string operators in Tcl and how the expr command evaluates expressions, with Docker-ready examples
In most languages, 2 + 2 is an expression the parser understands directly. Tcl is different. Because everything is a command and everything is a string, Tcl has no built-in arithmetic in its core syntax. Instead, operators live inside a single command: expr. When you want to add, compare, or apply logic, you hand an expression to expr, and it parses and evaluates the operators for you.
This design is a direct consequence of Tcl’s philosophy. The interpreter doesn’t know that + means addition—it just sees commands and arguments. The expr command is where a small, C-like expression language is embedded. Understanding this split is the single most important idea for using operators in Tcl correctly.
Two habits will save you endless trouble. First, always brace your expressions: write [expr {$a + $b}], not [expr $a + $b]. Bracing lets expr do the variable substitution itself, which is faster (it compiles to bytecode) and safer (it avoids double-substitution bugs). Second, remember that Tcl has separate operators for numbers and strings—== compares numerically while eq compares as strings. This tutorial walks through arithmetic, comparison, logical, string, and assignment operators, all the way to precedence.
Arithmetic Operators
Arithmetic operators only have meaning inside expr. Note that division between two integers produces an integer (it truncates), while introducing a single floating-point operand switches the whole expression to floating-point math.
Create a file named arithmetic.tcl:
| |
The ** operator is exponentiation (17 to the 5th power). The % operator is the remainder after integer division.
Comparison Operators
Comparison operators return 1 for true and 0 for false—Tcl has no separate boolean type, so truth is just an integer. The numeric operators (==, !=, <, >, <=, >=) coerce their operands to numbers. For comparing strings, Tcl provides dedicated word operators (eq, ne, lt, gt, le, ge) that compare lexically without any numeric coercion.
Create a file named comparison.tcl:
| |
Using eq/ne instead of ==/!= for strings avoids a classic Tcl surprise: the string "10" and the string "10.0" are equal numerically (== gives 1) but different as strings (eq gives 0).
Logical Operators and the Ternary
Logical operators combine boolean results: && (and), || (or), and ! (not). Like C, Tcl’s && and || short-circuit. Tcl also supports the C-style ternary operator condition ? a : b, which is the idiomatic way to choose a value based on a test.
Create a file named logical.tcl:
| |
The ternary expression returns a string here ("Pass" or "Fail"), showing that expr results aren’t limited to numbers.
String and List Operators
Tcl has no + operator for joining strings—that would be ambiguous in a language where every value is a string. Concatenation is done through variable substitution inside double quotes, or with the append command, which mutates a variable in place. Within expr, the in and ni (not-in) operators test list membership.
Create a file named string_ops.tcl:
| |
The append command takes a variable name followed by any number of values to tack onto it—an efficient way to build up strings without repeated reassignment.
Operator Precedence and Assignment
Precedence in expr follows the same rules you know from C and ordinary math: * and / bind tighter than + and -, and parentheses override the defaults. The ** power operator is right-associative, so 2 ** 3 ** 2 means 2 ** (3 ** 2).
Tcl has no += or ++ operators. For integer counters, use the incr command. For anything else, reassign with set and expr.
Create a file named precedence.tcl:
| |
Running with Docker
The efrecon/tcl:latest image uses tclsh as its entrypoint, so you pass the script path directly.
| |
If you have Tcl installed locally, run any file with tclsh arithmetic.tcl.
Expected Output
Running arithmetic.tcl:
Addition: 17 + 5 = 22
Subtraction: 17 - 5 = 12
Multiplication: 17 * 5 = 85
Division: 17 / 5 = 3
Modulo: 17 % 5 = 2
Power: 17 ** 5 = 1419857
Integer div: 17 / 5 = 3
Float div: 17.0 / 5 = 3.4
Running comparison.tcl:
x == y: 0
x != y: 1
x < y: 1
x > y: 0
x <= y: 1
x >= y: 0
s1 eq s2: 0
s1 ne s2: 1
s1 lt s2: 1
Running logical.tcl:
Can drive: 1
Is minor: 0
Not licensed: 0
Senior or OK: 1
Score 72: Pass
Running string_ops.tcl:
Full name: John Ousterhout
Hello, John!
banana in list? 1
grape not in list? 1
Running precedence.tcl:
2 + 3 * 4 = 14
(2 + 3) * 4 = 20
2 ** 3 ** 2 = 512
Counter: 6
After -2: 4
Total doubled: 200
Key Concepts
- Operators only work inside
expr— Tcl’s core syntax has no arithmetic.set x [expr {$a + $b}]is the pattern; bareset x $a + $bjust stores three separate words. - Always brace expressions —
[expr {$a + $b}]letsexprsubstitute variables itself, compiling to faster bytecode and avoiding double-substitution security bugs. Unbracedexpris a common source of errors. - Numbers and strings have different operators — use
==,!=,<,>for numeric comparison andeq,ne,lt,gtfor string comparison. Mixing them leads to surprises like"10" == "10.0"being true. - Booleans are just integers — comparison and logical operators return
1(true) or0(false);expralso acceptstrue/false/yes/noas boolean literals. - No string
+operator — join strings with"$a$b"substitution or theappendcommand; there is no overloaded+. - No
++or+=— increment integers withincr var ?amount?; for other updates, reassign withset var [expr {...}]. **is right-associative —2 ** 3 ** 2evaluates as2 ** (3 ** 2), matching mathematical convention but unlike most binary operators.- Bitwise operators exist too —
&,|,^,~,<<, and>>work on integers insideexpr, just like in C, plusin/nifor list membership.
Running Today
All examples can be run using Docker:
docker pull efrecon/tcl:latest
Comments
Loading comments...
Leave a Comment