10

\write16 sends to terminal, \message also does this. Why there are two commands for this and in which cases each one must be used?

Igor Liferenko
  • 7,063
  • 2
  • 14
  • 47

2 Answers2

10

Here's in D. Knuth's words

An ‘\immediate\write16’ differs from \message in that \write prints the text on a line by itself; the results of several \message commands might appear on the same line, separated by spaces.

Sample.tex

First page
\write16{** one **}  \message{** two **}

\vfill\eject
Second page
\immediate\write16{** one W **}\immediate\write16{** two W **} 
\message{** one M **}\message{** two M **}
\bye

sample.log shows

(sample.tex ** two ** [1{[....]/texmfs/data/pdftex/config/pdftex.map}
** one **
]
** one W **
** two W **
** one M ** ** two M ** [2] )
touhami
  • 19,520
1

Well, for the sake of completeness, another difference is that LuaTeX supports more than 16 streams (it supports 128), therefore unlike \message, \write16 might actually write to some code that allocates that stream.

Some alternatives include

  • Lua's print()
  • \write128, which is also valid in other engines
  • \message with ^^J/whatever \newlinechar is at the end
  • LaTeX's \typeout command which internally writes to the \@unused stream.

Remark, morewrites package does not touch stream 16 (it only uses 0-15 and 19...) so 16 is still safe.


Another difference, this one only for academical purpose, is that

  • \message expands tokens as it goes, similar to \csname … \endcsname, \pdfescapestring, \scantokens or \edef.

  • \write16 needs to first collect the arguments unexpanded (like \def or \toks0={…}), then fully expand it (with an \endwrite token put after the }) when it needs to be written.

    \immediate\write16 inherits this behavior as well. (it could do differently, but I assume this is for implementation simplicity)

Consequently, in these cases the behavior is different:

% given this.
\outer\def\someoutertoken{}

% then... \message{123 \noexpand\someoutertoken} % works %\immediate\write16{123 \noexpand\someoutertoken} % fails

\message{\iffalse}{\fi} % works %\immediate\write16{\iffalse}{\fi} % fails, produces a "incomplete iffalse" error message just like "\iffalse\someoutertoken\fi"

user202729
  • 7,143