# Is it really bad to use \makeatletter and \makeatother in a package or class file?

In my answer to this question What do \makeatletter and \makeatother do? I apparently wrote:

The commands should not be used within .sty and .cls files themselves as they may conflict with the catcode changes that occurs when package and class files are loaded.

In fact this particular line was added in by Will Robertson. So I'm curious: can someone come up with a concrete example of how having \makeatletter and \makeatother at the beginning and end of a package or class would affect another package?

I'm not talking about what happens if you leave one of them out, as discussed here:

How bad is slack \makeatother discipline really?

-

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:

1. First, the options and such are gathered.
2. Then the name of the current file (i.e. mypackage.sty), along with the catcode of @, are saved on a stack.
3. Then \makeatletter is run and, if appropriate, the requested file is loaded.
4. 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}
\begin{document}
\end{document}

\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 \inputs pgfkeys.code.tex, and that file, in turn, \inputs 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)

-
So the real moral is "don't \input files when you mean to \usepackage them". –  Ryan Reich Jul 8 '12 at 6:06
@RyanReich There's no reason why bar.tex should be a package. It could be an aux file, toc, out or anything. There's no reason to assume the use of \AfterPackage wouldn't work, so leaving @ as other at the end of a package is clearly an error. –  Stephan Lehmke Jul 8 '12 at 6:08
You're right. I guess this shows the importance of knowing why the default catcode regime in packages is what it is; i.e. how it happens. It happens at each package load. –  Ryan Reich Jul 8 '12 at 6:18