Tcl Part I · Module 2 · The Tcl Execution Model
Variable Substitution: $name
You have been writing $name since Module 1 without being told the rule behind it. The rule is small: Tcl reads the name as letters, digits and underscores, and stops at the first character that is not one of those. Nearly everything practical about variable substitution follows from that one sentence, including why ${name} exists, why a trailing letter can silently break a line, and why a dollar sign in ordinary text sometimes causes an error you did not expect.
Foundation12 min readTclPart IExecution ModelSubstitutionVariables
Part I · Module 2 · Chapter 2.4 · Variable Substitution: $name
1. What It Does
$name tells Tcl: replace this with the value stored under that name.
set language Tcl
puts $language
puts "Language: $language"Tcl
Language: TclBoth lines substituted. The second shows that substitution happens inside double quotes too — Chapter 2.7 explains why.
2. The Rule
Here is the whole thing:
After
$, Tcl reads letters, digits and underscores. It stops at the first character that is not one of those.
Nothing else to memorise. The rest of this chapter is that rule applied.
3. Watching the Name End
Each of these ends the name at a different character:
set unit cm
puts "plain: $unit"
puts "with dash: $unit-s"
puts "with dot: $unit."
puts "with slash: $unit/min"plain: cm
with dash: cm-s
with dot: cm.
with slash: cm/minIn every case Tcl read unit, stopped at the next character, and left that character alone. The dash, the dot and the slash are not part of the name, so they are ordinary text.
4. When the Rule Works Against You
Now a case where the rule does something you did not want:
set unit cm
puts "$units"Predict the output before reading on. Many people expect cms.
can't read "units": no such variable
while executing
"puts "$units""
(file "runon.tcl" line 2)Tcl did not read unit and then an s. s is a letter, so it is part of the name. Tcl looked for a variable called units, and there is not one.
Nothing is wrong with the rule. The rule is doing exactly what §2 says. The problem is that you wanted the name to end before the s, and nothing in the text said so.
${name} is how you say so:
set unit cm
puts "${unit}s"cmsThe braces mark where the name ends. Tcl reads unit, sees the closing brace, and the s after it is ordinary text.
5. A Second Case: Digits
The same thing happens with digits, and it is easier to miss:
set x 7
puts "$x9"can't read "x9": no such variableDigits are name characters, so x9 was read as one name.
6. The Dollar Sign in Ordinary Text
Here is the part most people get wrong, including anyone reasoning from memory. The intuition is "a dollar with nothing variable-like after it is just a dollar". That intuition is only half right.
It works when the next character cannot start a name:
puts "costs $ 5"
puts "price in $."
puts "ends with $"costs $ 5
price in $.
ends with $A space, a dot, and the end of the text all leave the $ alone.
But a digit can be part of a name:
puts "it costs $5"can't read "5": no such variableThat line looks like plain English and is a Tcl error. The 5 was read as a variable name.
The fix is to escape the dollar sign, which is Chapter 2.6:
puts "it costs \$5"it costs $57. Substitution Does Not Change the Word Count
Worth seeing once in this chapter, because it is the rule from Chapter 2.2 and it is what makes $name safe to use bare:
proc show {args} { puts "received [llength $args] word(s)" }
set path "my report.txt"
show $pathreceived 1 word(s)The value holds a space; the command still got one argument. You do not have to quote a variable to protect it.
8. Common Mistakes
Letting the name run on. "$units" when you meant "${unit}s". The error names a variable you never created, which is the clue.
Unescaped dollar signs in text. "$5" is a variable reference. §6.
Using ${} everywhere. It works, but it adds noise. Use it where the boundary is genuinely ambiguous.
Expecting $ to work inside braces. It does not — braces stop substitution. That is Chapter 2.8, and it is deliberate rather than a limitation.
9. Exercises
Exercise 1 — predict the boundary. With set base report, write down what each line prints, then check:
puts "$base"
puts "$base.txt"
puts "$base_final"
puts "${base}_final"
puts "$base-final"One of these is an error. Which, and why?
Exercise 2 — fix a price. Make this line print Total: $42 exactly:
puts "Total: $42"Exercise 3 — two ways to join. With set prefix core, produce the text core_backup twice: once using ${...}, and once by building it with a separate set. Which reads better to you, and would your answer change if the prefix were used ten times in one line?
Exercise 4 — read the error backwards. You see can't read "logfile2": no such variable, and you know a variable called logfile exists. What does the source line probably look like, and what is the one-character fix?
10. Remember
$namesubstitutes the value stored under that name.- The name is letters, digits and underscores, and it ends at the first character that is not one of those.
${name}exists to end a name early, for when the next character would otherwise join it.- A dollar followed by a letter, digit or underscore is a variable reference — including
$5. Escape it as\$when you mean a literal dollar. - A dollar followed by a space, punctuation, or end of text is just a dollar.
- Substituting a value never changes the word count, so a bare
$nameis safe even when the value contains spaces. - Braces stop substitution entirely. Chapter 2.8.
Next: the brackets, which run a command and use what it returns.
Where this fits
Part of the Tcl curriculum.
