Variables and substitution
The cards come in more than one shape: a command to explain, and a snippet with a fault to find. A missed card returns later in the round and starts the schedule over. A card answered correctly moves up the schedule and next appears after 1, 3, 7, then 21 days. Keys 1 to 4 choose an option, h shows a hint, and Enter moves on. A hint keeps the card where it is on the schedule. An ordering card is answered by clicking its items in order, and one wrong click ends it. Time values are in nanoseconds. Progress is stored in this browser.
All 9 cards in this section, with answers
-
set period 2.0 set half [expr {$period / 2}] puts "half is $half"Brackets run a command and substitute its result; quotes substitute variables.
Hint: Three kinds of bracket appear here. Ask what each one does before the command runs.
Square brackets are the command ones. Substitution happens once, before the command runs:
[...]is replaced by the result of the command inside it, and$nameby the variable's value. Braces,{...}, suppress both, which is why they appear around expressions and procedure bodies. Tcl reference -
set n 4 set a [expr {$n * 2}] set b [expr $n * 2]Both work here, but the braced form is safer and faster.
Hint: Both give 8. Ask what happens to the expression text before expr sees it.
Without braces the substitution happens first, so
exprreceives the values as text and must parse them again. That is slower, and a value that contains an operator or a space can change the expression's meaning. Braced expressions are the rule in tool scripts. Tcl reference -
set x 0.5 set y [expr {$x + 1}]Values are strings; `expr` is what interprets them as numbers.
Hint: Ask what type x has before expr looks at it.
Everything in Tcl is a string at the language level, and commands interpret it. This is why arithmetic needs
expr, why comparing numbers as strings misleads, and why a stray space in a value can turn into two arguments. Tcl reference -
incr count append names " $cell"Adds one to a numeric variable, and adds text to the end of a string.
Hint: Two shorthands. Ask what each saves you writing.
incrtakes an optional step, soincr count 5adds five and a negative value subtracts.appendgrows a string in place; the list equivalent islappend, which keeps list structure instead of concatenating text. Tcl reference -
set name clk puts "the clock is $name" puts {the clock is $name}Quotes substitute variables and commands; braces pass the text through.
Hint: Read the second line and the third as the interpreter would.
The second line prints the clock is clk and the third prints the dollar sign and the name. This is the single most useful rule in the language: braces mean literally this, quotes mean fill it in. It is why procedure bodies and expressions are braced. Tcl reference
-
set name clk expr { $name == "clk" } expr { $name eq "clk" }Both compare here, but only the second is always a string comparison.
Hint: One of the two operators works on numbers first.
The numeric operator converts when it can, so comparing 1.0 with 1 is true and comparing 0x10 with 16 is true. That is rarely what a script comparing names wants, and it is a classic source of a condition that is true for the wrong reason. Use
eqandnefor text. Tcl reference -
set stage place puts "${stage}_done"The braces mark where the variable name ends.
Hint: Ask where the interpreter would decide the variable name ends.
Without them the interpreter looks for a variable called
stage_doneand fails. A name runs to the first character that cannot be part of one, and an underscore can be, which is why this bites when building file names. Tcl reference -
set ::top_module gcd puts $::env(HOME)The variable at the top level, reachable from inside any procedure.
Hint: Two colons in front of a name. Ask which variable is meant.
A procedure sees only its own variables unless it says otherwise, and the leading colons name the global namespace directly, which avoids having to declare it. The environment array is the common case, since a flow is usually configured through it. Tcl reference
-
set half [expr $period / 2]The value is substituted into the expression before it is parsed.
Hint: Ask what the expression looks like after substitution, if the variable holds text.
With a plain number it works. If the variable holds
2+1, the expression becomes2+1 / 2, which is not what was meant, and a value from a file or a tool can hold anything. Bracing the expression also lets it be compiled once rather than reparsed on every pass of a loop. Tcl reference