Skip to content
VLSI Mentor

Tcl Part I · Module 1 · Introduction to Tcl

puts: Making a Script Say Something

You have been using this command on trust since the first page, and it earns a chapter of its own for two reasons. It is your only window into a running script — Tcl throws away every result you do not explicitly ask to see, so until much later in the track `puts` is how you find out what your program is doing. And it is the first command whose behaviour visibly depends on Tcl splitting your line into words, which means a small change in quoting does not merely change the output, it can change which arguments the command thinks it received. The error you get when that happens is unusually informative, and reading it is the most efficient way to learn what this command actually accepts.

Foundation13 min readTclPart IFundamentalsputsOutput

Part I · Module 1 · Chapter 1.7 · puts: Making a Script Say Something

1. Why This Command Matters More Than It Looks

Chapter 1.5 §3 established something that makes this command essential rather than merely useful: a Tcl script discards the result of every command unless you do something with it. Compute a value, and it is gone. A script can do a great deal of correct work and tell you nothing.

So puts is not just "how to print". For the whole of Part I it is the only way to observe a running program. When a script misbehaves, the fastest diagnostic available is to add a puts and look at what is actually there rather than what you assumed.

Worth learning properly, then.

2. The Simplest Form

One argument — text to display, followed by a line break:

Azvya Education Pvt. Ltd.VLSI Mentor
hello.tcl
puts "starting the check"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
starting the check

The quotes are not part of the message. They group the words starting, the and check into a single argument so that puts receives one piece of text rather than three.

That claim is easy to state and easy to disbelieve, so the next section makes it visible.

3. The Quotes Are Doing Real Work

Try a single word with no quotes at all:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts hello
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
hello

That works. One word is one argument, so grouping it changes nothing.

Now two words with no quotes. Predict the output before reading on:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts hello there

Most people expect hello there. Here is what actually happens:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
can not find channel named "hello"
    while executing
"puts hello there"
    (file "two-words.tcl" line 1)

Read that error closely, because it is telling you something precise. Tcl split the line into three words — puts, hello, there — and handed puts two arguments. Given two arguments, puts treats the first as somewhere to write and the second as the text. So it looked for a destination called hello, and there is no such thing.

Nothing was misspelled. The command received exactly what you typed; your assumption about how it would be grouped was wrong.

Add a third word and the error changes again:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts hello there world
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
bad argument "world": should be "nonewline"
    while executing
"puts hello there world"
    (file "three-words.tcl" line 1)

Three arguments now, and puts expects the first of three to be an option. hello is not an option, so it complains — naming the only option it accepts, which is useful information we will use in §7.

With quotes, all of this goes away:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts "hello there world"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
hello there world

One argument, because the quotes grouped it.

4. Ask the Command What It Takes

There is a shortcut to the signature, and it is worth knowing as a technique rather than a trick. Call puts with no arguments at all:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
wrong # args: should be "puts ?-nonewline? ?channelId? string"
    while executing
"puts"
    (file "nothing.tcl" line 1)

Tcl answered with the command's own usage line. Reading Tcl's convention:

  • ?...? marks an optional part. So -nonewline and channelId are both optional.
  • string has no question marks, so it is required.

That one line explains every result in §3. puts hello there supplied channelId and string; puts hello there world supplied all three and got the option wrong.

5. Where the Text Goes

The optional channelId is a destination. Two are open for you from the start:

  • stdout — standard output, the default. This is where your results go.
  • stderr — standard error, intended for diagnostics and problems.

These two lines are equivalent in effect:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts "to standard output"
puts stdout "to standard output"

The explicit form is rarely written, because the default is what you want nearly always. Its value is in making §3 comprehensible: stdout occupies the same argument slot that hello wrongly landed in.

6. Why stderr Is Worth Using

Both streams normally appear in your terminal, so on screen the distinction looks like nothing:

Azvya Education Pvt. Ltd.VLSI Mentor
streams.tcl
puts "the result: 42"
puts stderr "warning: input file was empty"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
the result: 42
warning: input file was empty

The difference appears the moment anything other than a human consumes the output. The two streams can be separated. Keeping only the results:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
tclsh streams.tcl 2>/dev/null
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
the result: 42

Keeping only the diagnostics:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
tclsh streams.tcl 2>&1 >/dev/null
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
warning: input file was empty

That is the whole point. If a script's results and its commentary go to the same stream, anything processing those results has to somehow tell them apart. If they are separated at the source, it does not.

The rule is simple enough to adopt permanently:

What the script is for goes to stdout. What the reader needs to know about the run goes to stderr.

7. Suppressing the Line Break

puts normally ends with a newline. The one option it accepts turns that off:

Azvya Education Pvt. Ltd.VLSI Mentor
nonewline.tcl
puts -nonewline "checking "
puts -nonewline "and checking "
puts "done"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
checking and checking done

Three commands, one line of output. The first two wrote without a line break, and the third ended it.

Order matters when combining the option with a channel — the option comes first, exactly as the usage line in §4 shows:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts -nonewline stderr "working... "
puts stderr "finished"
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
working... finished

8. Failure Modes, Collected

Four, and you have met three already.

What you wroteWhat you getWhy
puts hello therecan not find channel named "hello"Two arguments: the first is read as a destination. Quote the text.
puts hello there worldbad argument "world": should be "nonewline"Three arguments: the first must be the option. Quote the text.
putswrong # args: should be "puts ?-nonewline? ?channelId? string"string is required. Usefully, this prints the usage.
puts nosuchchannel "text"can not find channel named "nosuchchannel"That destination does not exist.

Three of the four are the same mistake — unquoted text being split into separate arguments. That is worth noticing, because it is the shape of a large fraction of all Tcl beginner errors, not just this command's.

9. Exercises

Exercise 1 — reproduce all three errors. In a file, trigger puts hello there, then puts hello there world, then puts alone. One at a time, since the first one stops the script. Read each message and name which argument slot caused it.

Exercise 2 — derive the behaviour from the usage line. Using only puts ?-nonewline? ?channelId? string, predict what each of these does. Then run them.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
puts stdout hello
puts -nonewline hello
puts -nonewline stdout hello

Exercise 3 — separate the streams. Write a script that prints one result line and two diagnostic lines, with the results on stdout and the diagnostics on stderr. Verify by running it twice, once with 2>/dev/null and once with 2>&1 >/dev/null, and confirm each shows only what it should.

Exercise 4 — one line from three commands. Produce the output a-b-c followed by a line break, using exactly three puts commands and no text containing more than one letter. You will need -nonewline and the separators.

Exercise 5 — use the technique, not the chapter. You have not been taught string length. Without searching, call string with no arguments and then string length with no arguments, and from the usage lines alone work out how to display the length of the text report.txt. This is §4 used the way it is meant to be used.

10. Summary

  • puts is your only window into a running script. Tcl discards results you do not ask to see.
  • The usage is puts ?-nonewline? ?channelId? string. ?...? means optional; string is required.
  • Spaces separate arguments; quotes group text into one argument. puts hello there passes two arguments, not one piece of text.
  • The resulting errors disclose the signature. can not find channel named "hello" is Tcl telling you the first of two arguments is a destination.
  • Calling a command with no arguments usually prints its usage. Faster than looking it up.
  • stdout is for what the script is for; stderr is for what the reader needs to know about the run. The streams can be separated downstream, which is the whole reason to keep them apart at the source.
  • -nonewline suppresses the line break, and must come before a channel. Unterminated -nonewline output can sit in a buffer rather than appearing.
  • Three of the four common failures are the same mistake: unquoted text split into separate arguments.

The next chapter deals with the other thing you have been writing without explanation — comments — and with a rule about them that is specific to Tcl and catches everybody exactly once.

Where this fits

Part of the Tcl curriculum.