Tcl Part I · Module 3 · Values, Variables, and Expressions
Variable Names, and What Tcl Allows
This chapter resolves something that looks like a contradiction. Chapter 2.4 told you a variable name is letters, digits and underscores. That was true about what the dollar sign will read. It is not true about what a name may actually contain, which is very nearly anything — including spaces. Both rules are real and they govern different things, and once you see that, the brace form you met earlier stops being a special case and becomes the obvious bridge between them.
Foundation10 min readTclPart IValuesVariablesNaming
Part I · Module 3 · Chapter 3.3 · Variable Names, and What Tcl Allows
1. The Normal Case
In practice, nearly every variable you write looks like this:
set total_count 0
set runDirectory "output"
set x 1
set MAX_RETRIES 3
puts "$total_count $runDirectory $x $MAX_RETRIES"0 output 1 3Letters, digits and underscores. That is the whole of what you need, and §6 gives the convention worth following. The rest of this chapter is about why Tcl allows more, and what to do when you meet it.
2. A Name Can Contain Almost Anything
set takes the name as an ordinary word, and it does not inspect it. So any word is a legal name — including one with a space in it:
set {odd name} 1
set {a.b} 2
set {3rd} 3
puts "odd name = ${odd name}"
puts "a.b = ${a.b}"
puts "3rd = ${3rd}"odd name = 1
a.b = 2
3rd = 3All three worked. A name starting with a digit, a name containing a dot, and a name containing a space are all fine.
You can confirm Tcl really stored them under those names:
set total_count 0
set {odd name} 1
puts [lsort [info vars *o*]]auto_path {odd name} tcl_platform tcl_version total_countThere it is, listed alongside the ordinary ones.
3. Two Different Rules
Now the apparent contradiction. Try reading that variable the usual way:
set {odd name} 1
puts "$odd name"can't read "odd": no such variableThe variable exists. Tcl just did not look for it, because $ stopped reading the name at the space.
Here are the two rules side by side, and keeping them apart is the point of this chapter:
| Rule | What it governs |
|---|---|
| A name may contain almost any character | what set will accept as a name |
$ reads letters, digits and underscores, then stops | what the dollar sign will look up |
They are not in conflict. One is about storage, the other about one particular way of reading.
4. ${...} Is the Bridge
Chapter 2.4 introduced ${name} as a way to end a name early. Now you can see its general form: the braces say exactly which characters are the name.
set {odd name} 1
puts "${odd name}"
puts [set {odd name}]1
1Both work. The brace form tells $ where the name ends; the set form takes the name as a word, which it was always able to do — Chapter 3.2 §4.
So ${unit}s from Chapter 2.4 and ${odd name} here are the same mechanism used for two different reasons.
5. Why You Will Not Use This
Honest summary: unusual names are something to recognise, not something to write.
- A name with a space in it has to be braced at every single use, forever.
- Tools, editors and your own searching work less well.
- Anyone reading your code will stop and wonder whether it was deliberate.
Where you will genuinely meet odd names is in data that came from somewhere else — a configuration file, a report, a tool's output — and someone used the incoming text as a variable name. The better answer in that situation is a dictionary or an array, which are designed for keys that are arbitrary text. Module 7 covers both.
6. The Convention Worth Following
Tcl has no enforced style, but there is a widely used one:
set retry_limit 3 ;# lowercase with underscores — ordinary variables
set MAX_RETRIES 3 ;# all capitals — a value treated as fixed- Lowercase with underscores for ordinary variables. Readable, and the most common style in Tcl code.
- All capitals for values you intend not to change. Tcl does not enforce this — nothing stops you reassigning
MAX_RETRIES— so it is a message to other engineers rather than a guarantee. - Descriptive over short.
retry_limitbeatsrl. The cost of typing it is paid once; the cost of decoding it is paid by every reader. - Avoid leading underscores and single letters except for short-lived loop variables.
7. Names to Avoid
A few names are already in use by Tcl itself, and overwriting them causes confusing failures rather than clean errors:
puts "Tcl already uses: [lsort [info vars tcl_*]]"
puts "and: env, argv, argc, argv0, auto_path"Tcl already uses: tcl_interactive tcl_library tcl_patchLevel tcl_pkgPath tcl_platform tcl_rcFileName tcl_version
and: env, argv, argc, argv0, auto_pathThe exact list depends on your interpreter and how it was started, so run it rather than trusting this one.
None of these is reserved in the sense that Tcl will stop you. They are simply variables Tcl or your script's environment already relies on. env in particular holds the environment variables, and a script that reassigns it will break in ways that look unrelated.
The practical rule: do not create variables beginning tcl_, and leave env, argv, argc and argv0 alone unless you are deliberately working with them. Module 15 covers what they are for.
8. Common Mistakes
Assuming $ can read any legal name. It cannot — §3. Brace it.
Using an odd name because it works. It works and it costs you at every use. §5.
Getting the case wrong. $runDir and $rundir are different variables and neither error nor warn about the other.
Using a variable name computed from external text. Use a dictionary or array instead — §5.
Overwriting env or something tcl_-prefixed. §7.
9. Exercises
Exercise 1 — create and read an odd name. Make a variable called build id (with a space), store 42 in it, and print it. Then try to print it without braces and read the error.
Exercise 2 — explain the contradiction. In two sentences, explain to a colleague why Chapter 2.4 said names are letters, digits and underscores while this chapter says they can contain anything. Use the two-rule table in §3.
Exercise 3 — case sensitivity. Set limit to 1 and Limit to 2, print both, then predict what puts $LIMIT does before running it.
Exercise 4 — the better design. You are reading a configuration file with lines like timeout = 30. A colleague's script does set $key $value for each line. Give two concrete reasons this is a poor choice, and name what you would use instead.
Exercise 5 — inspect the environment. Run puts [lsort [info vars]] in a fresh script. Which variables exist that you did not create? Pick one and say why a script should not reassign it.
10. Remember
- In practice, use letters, digits and underscores. That covers everything you will write.
- A name may legally contain almost any character, including spaces —
setdoes not inspect the name. $reads letters, digits and underscores and stops. Two different rules: what a name may be, and what$will read.${...}bridges them by saying exactly which characters are the name.- Unusual names are for recognising, not writing. Use a dictionary or array for arbitrary keys.
- Names are case-sensitive. Check capitalisation first when a variable looks empty.
- Leave
tcl_*,env,argv,argcandargv0alone unless you mean to use them.
Next: how to ask whether a variable exists before you read it, and how to remove one.
Where this fits
Part of the Tcl curriculum.
