Is it really bad to use \makeatletter and \makeatother in a package or class file?
First of all, \makeatletter
is unnecessary in .sty
or .cls
files, as the default catcode regime includes it; this is presumably to encourage package writers to hide their macros using @
-laden names. For this reason, I believe that using this command is harmless in package files.
However, using the pair of commands together is harmful, because unlike in a document, you do not want to return to the @ = other
setup within the package. These are document commands and the standard ordering \makeatletter \makeatother
assumes that \makeatother
is actually undoing the previous change, whereas in packages, it is the one making the change.
Edit: Here is a more informed answer. According to source2e.pdf
, the following scheme is used to load packages and classes:
- First, the options and such are gathered.
- Then the name of the current file (i.e.
mypackage.sty
), along with the catcode of@
, are saved on a stack. - Then
\makeatletter
is run and, if appropriate, the requested file is loaded. - Afterwards, the stack is popped and the pre-package-load state restored.
In other words, the following ignorant code has no effect at all:
\documentclass{article}
\usepackage{bad}
\begin{document}
\end{document}
bad.sty:
\makeatletter
\makeatother
\RequirePackage{unsuspecting}
However, it is quite possible that a package does not use \RequirePackage
, but just \input
. In that case, the catcode is not protected and indeed, errors can arise, as you can check yourself by making bad.sty
, for example:
\makeatletter
\makeatother
\input{pgfkeys.sty}
If that seems artificial, have a look at pgfkeys.sty
itself: it \input
s pgfkeys.code.tex
, and that file, in turn, \input
s pgfkeysfiltered.code.tex
. Presumably, the author felt himself safe once within his own package, but did not suspect that someone else might circumvent the package-loading protection mechanisms also!
This was a lot more serious in LaTeX2.09 as there LaTeX just executed \makeatletter
once before handling all the .sty
files (LaTeX2.09 didn't gave the .cls
/.sty
distinction). So it was a common problem, almost a FAQ, that packages were released that executed \makeatother
at the end of the file and they worked in isolation but broke any following "style files" (aka packages).
So one of the first things done for 2e was to reset the catcode of @
on loading each package, maintaining a stack so that the catcode is restored at the end of the package to what it was before. Thus by design it is hard to find an example where a rogue \makeatother
at the end of a package does harm.
That said, it's better practice not to fall than to rely on a safety net.
As long as you're aware not to do bad things inside your own package (like Ryan Reich's example), you seem to be safe within the bounds of what LaTeX offers.
But still dangers lurk around the corner.
If I say
\usepackage{afterpackage}
\AfterPackage{foo}{\input{bar}}
\usepackage{foo}
and inside foo.sty
\makeatother
and inside bar.tex
\protected@edef\baz{quux}
then I get an error because @
is not a letter (which doesn't happen without the \makeatother
).
(the main point of this answer is of course that the (unsuspecting) person using \AfterPackage
is not neccessarily the same as the package author)