Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

The reason for using \makeatletter/\makeatother has been discussed in many places, for instance in this question.

However I think that this trick of playing around with the "@" character is itself quite a hack. Couldn't the temporary redefinition of @'s catcode lead to problems? This might not be the practically most commonly occurring usage scenario, but if a section of code embraced by \makeatletter/\makeatother uses a macro \somemacro and we are used to applying this macro to certain arguments without braces, as in \somemacro@, couldn't this break code? Also, considering this possibility, is there a non-contrived use case in which such breakage might occur?

(Yep, this is a question that likely belongs into the domain "theory", but familiarity with parsing matters and compilation gives me a desire to see this discussed/documented.)

share|improve this question
    
I like this question. However, the only case this problem has bitten me was during debugging, when I forgot to say \makeatletter. But I'd love to hear what really experienced TeX users/programmers have to say. –  mbork Sep 24 '12 at 8:07
add comment

1 Answer

up vote 13 down vote accepted

When you want to directly use a macro with an @ in its name (at-macro, from now on), then you have to make sure that @ is considered a letter, that is the call must be after a \makeatletter declaration.

However normal macros that are defined in terms of at-macros don't need to be used in such a regime. Let's look at an example.

The LaTeX kernel defines \item as follows:

\def\item{%
  \@inmatherr\item
  \@ifnextchar [ {\@item}{\@noitemargtrue \@item[\@itemlabel]}%
}

and it does so where \makeatletter is in force. When the \def is executed, TeX stores \item and its replacement text in memory, but in a form that is independent of the actual characters that form the names of the used control sequences. Thus, when \item appears in your document (where \makeatother is usually in force), the fact that its expansion contains at-macros is irrelevant as far as the expansion process is concerned: TeX retrieves from its memory the meaning of \item in the internal form and the same happens when the first control sequence, \@inmatherr, must be expanded.

To the contrary, if you need to modify the definition of \item in order to add something at the beginning, this has to be made properly:

\makeatletter
\def\item{%
  \typeout{Doh! An item!}%
  \@inmatherr\item
  \@ifnextchar [ {\@item}{\@noitemargtrue \@item[\@itemlabel]}%
}
\makeatother

since you are referring to at-macros in the body of the definition. Without \makeatletter, the line \@inmatherr\item would be parsed (I use • to separate one token from another)

\@•i•n•m•a•t•h•e•r•r•\item

that is, eleven tokens and not two! This is because in normal regime @ is not a letter: when TeX is looking for a command name because it has found a backslash, any non-letter immediately stops the scanning and the command name will be formed by that non-letter.

What's a letter? Any character with category code 11 at the moment the scanning takes place. But, I repeat, once the scanning has been performed, the control sequence enters TeX in an internal format that's independent of category codes.

Looking at your example with \somemacro@, it's "easy" to distinguish the two cases:

\makeatletter
\somemacro@ % <- ONE token
\makeatother
\somemacro@ % <- TWO tokens

So, if you have defined both \somemacro@ (as an at-macro) and \somemacro, in a normal place of the document the combination \somemacro@ will expand \somemacro and not the at-macro. In fact, the scanning for a control sequence name will be stopped by @, which is not a letter in the document (if you haven't done \makeatletter, of course).

A doubt can arise for the following:

\makeatletter
\def\somemacro@#1{Do something smart with #1}
\def\somemacro#1{\somemacro@{(#1)}}
\makeatother

and the input (under normal conditions, that is, \makeatother)

\somemacro@

Now these are two tokens: \somemacro•@, so @ will be the argument to \somemacro and the final result would be printing

Do something smart with (@)

It takes a while to digest these tricks; but once one realizes that TeX works with the tokens it forms by reading the input file and works on them after translating into an internal format (which is irrelevant for the user to know), things begin to go more smoothly.

share|improve this answer
    
Great! Now let's say that \somemacro is defined elsewhere (and let's leave the question open whether you also define \somemacro@ in the "makeat"-block). If I say want to print something containing the letter "@" in that block, the original \somemacro-command won't be found, right? And if this is so, is my understanding correct that this can only be an issue with direct "@"-letters in the input? (That is, that's the only case I need to in theory worry about.) –  Lover of Structure Sep 25 '12 at 19:08
    
@user14996 No, in a \makeatother context, \somemacro@ are two tokens that will never be interpreted as the macro with name "somemacro@", be it defined or not. –  egreg Sep 25 '12 at 21:02
    
Yes, but what I meant is that in a \makeatletter context, the string \somemacro@ will always be interpreted as a single token, and thus if I'm used to writing \somemacroSOMETOKEN (because I want to use the macro \somemacro, not a macro \somemacro@) instead of the parenthesized \somemacro{SOMETOKEN}, I'm in trouble, correct? Thus I'm wondering about the range of practical cases where this can lead to trouble and if supplying the single-token argument @ is really the only case. If so, it's valuable to have it be stated somewhere (like on this forum). –  Lover of Structure Sep 26 '12 at 8:55
1  
@user14996 In the "programming environment" (where \makeatletter is in force, essentially) one must be quite careful; a final @ in a macro name may be a problem, but there are many other small quirks that experience will help in avoiding. –  egreg Sep 26 '12 at 9:02
    
To rephrase my point: the class of problem cases I had in mind is "whenever I supply a single @-argument without curly braces to an @-less macro name, I need to be aware that things are parsed as one token in the 'programming environment', not the intended two". That's all my question was about. And supplying curly braces already fixes that, if I'm right. Anyways, I think we're in agreement. –  Lover of Structure Sep 26 '12 at 9:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.