# Catcode change doesn't take effect

Why does the following TeX manuscript result in an error upon compilation with TeX Version 3.14159265 (TeX Live 2017)?

\catcode}=12}\bye


The error is:

! Too many }'s.

l.1 \catcode}=12}
\bye


What I expected to happen was that the compilation would complete successfully and the resulting dvi file would consist of the single character } (right brace).

This question is related to this one but different in that I'm not interested in how to print out a right brace, but rather in why the described method for doing so fails.

• I think you need a space after the number \catcode}=12 }\bye – clemens Jun 22 '17 at 9:02
• @clemens: Adding a space after the number indeed allows the compilation to complete, however the output is not a right brace but rather what looks like a quotation mark ". – Evan Aad Jun 22 '17 at 9:05
• @EvanAad you get the character in position 125 of the current font which is not always the shape } try it with \tt – David Carlisle Jun 22 '17 at 9:07
• computer modern roman, the default font in plain tex does not have a character with shape }. – David Carlisle Jun 22 '17 at 9:09

Your input fails for the reasons explained in your last question, you need

\catcode}=12 }\bye


so the number is finished before } is tokenised.

• Adding a space after the number indeed allows the compilation to complete, however the output is not a right brace but rather what looks like a quotation mark ". – Evan Aad Jun 22 '17 at 9:06
• @EvanAad you get the character from position 125 in the current font. Try \tt in front if you want a font with an encoding closer to ascii. – David Carlisle Jun 22 '17 at 9:07
• Thanks. But why doesn't TeX realize that the number has ended upon encountering the second }? If, for instance, I change the original manuscript by adding the @ character, whose catcode is 12, between the number and the right brace, the manuscript compiles successfully and the output is @} (or rather @" for the reason mentioned in your comment). – Evan Aad Jun 22 '17 at 9:13
• Nevermind, I think I know the answer. The reason is that it is the TeX "stomach" that decides when the number ends, but the stomach only "sees" tokens, so in order to "see" the right brace it has to be tokenized by the "mouth", which tokenizes it with the original catcode 2, because the catcode won't change until the "stomach" has finished processing the \catcode command. – Evan Aad Jun 22 '17 at 9:23

When TeX is looking for a number it continues scanning tokens and expanding them until finding an unexpandable token that cannot be interpreted as a digit (in the already set radix, default decimal).

If this unexpandable token is a space token, it gets ignored (only one, though).

This means that with

\catcode}=12}


the assignment has not yet been performed when the number is complete, and } has been tokenized with its current category code, that is, 2.

Always finish your constants with a space. Quoting the TeXbook:

For best results, always put a blank space after a numeric constant; this blank space tells TeX that the constant is complete, and such a space will never “get through” to the output. In fact, when you don't have a blank space after a constant, TeX actually has to do more work, because each constant continues until a non-digit has been read; if this non-digit is not a space, TeX takes the token you did have and backs it up, ready to be read again. (On the other hand, the author often omits the space when a constant is immediately followed by some other character, because extra spaces do look funny in the file; aesthetics are more important than efficiency.)

This is different from other assignments:

\def\foo{1} % just for an example
\chardef\foo=12\foo


will not be equivalent to \chardef\foo=121, because in these cases TeX temporarily sets \foo as equivalent to \relax, until it can perform the assignment. So the second \foo stops the search for digits and no expansion of \foo will be done. On the other hand

\chardef\foo=12 \foo


works the same and is clearer.

• Thanks. A couple comments. 1. You ended your answer with "works the same and is clearer." Works the same as what? Not the same as the 1st example. 2. The 1st example can also be explained by the following sentence from the TeXbook (1st paragraph on p. 207): "TeX requires the tokens in a numerical constant to be digits, after macro expansion". The last occurrence of \foo is still a macro as long as the TeX "stomach" has not finished "digesting" the \chardef, and therefore this macro is expanded to 1 and the "stomach" "sees" this 1 as the third digit. – Evan Aad Jun 22 '17 at 10:17
• @EvanAad “works the same” as \chardef\foo=12\foo. Your final analysis is wrong: when TeX scans \chardef\foo it temporarily makes \foo equivalent to \relax`, as explained in the text. – egreg Jun 22 '17 at 14:17