# How to make @ a letter within a macro

I defined a macro which is essentially a wrapper for \meaning to check macro definitions

\def\whatis#1{{\ttfamily\string#1: \meaning#1}}


(The actual form I'm using goes one step further and checks whether the command is robust, but this is irrelevant here.) More often than not, the result involves some internal macro containing the token @. If I want to check this macro, I must then write something like

\makeatletter
\whatis\MacroNameWith@InIt
\makeatother


As I'm very lazy :-) I would like to activate \makeatletter within the scope of \whatis, so I tried

\def\whatis#1{{\makeatletter\ttfamily\string#1: \meaning#1\makeatother}}


(Actually I'd guess that \makeatother isn't necessary because of the grouping.) Needless to say, this isn't working, otherwise I wouldn't be posting this question :-)

My questions:

1. Why is this not working?
2. How can I define \whatis such that \whatis{\MacroNameWith@InIt} behaves as I wish?
• No the url package does not change catcodes. Steven shows how to do what you ask but note that the resulting command is like \verb and can not be used in the argument of any other macro. Oct 12, 2016 at 15:58
• catcode changes like \makeatletter (which is \catcode@=11) affect the catcode table which is only used to convert input characters into tokens. By the time you are in the replacement text of a macro the argument passed as #1 has already been tokenized so the catcode change has no effect (unless you use \scantokens which is the same as writing it out to a file and then reading the characters back in, but uses an internal buffer for efficiency. Oct 12, 2016 at 16:00

The key is to have the \makeatletter invoked before an argument hits the macro. Thus, here, I move the argument absorption to \whatisaux, after the \makeatletter is invoked by \whatis.

\documentclass{article}
\makeatletter
\def\whatis{\makeatletter\whatisaux}
\def\whatisaux#1{{\ttfamily\string#1: \meaning#1}\makeatother}
\makeatother
\begin{document}
\whatis\MacroNameWith@InIt
\end{document}


A much simpler way to avoid the problem for the specific use case is to change the input syntax not to require the \

\def\whatis#1{\texttt{#1: \expandafter\meaning\csname #1\endcsname}}
\whatis{MacroNameWith@InIt}


Steven shows how to do what you ask but note that the resulting command is like \verb and can not be used in the argument of any other macro.

catcode changes like \makeatletter (which is \catcode\@=11 ) affect the catcode table which is only used to convert input characters into tokens. By the time you are in the replacement text of a macro the argument passed as #1 has already been tokenized so the catcode change has no effect (unless you use \scantokens which is the same as writing it out to a file and then reading the characters back in, but uses an internal buffer for efficiency).

• @campa I think David's 2nd comment at your original question answers the above question: the argument is tokenized (and catcodes are applied) prior to reaching the \makeatletter. Those digested tokens of the argument will have the @ as catcode=12, regardless of subsequent attempts to change the future catcode behavior of @. Oct 12, 2016 at 16:49
• @campa as requested Oct 12, 2016 at 17:26
\def\whatis#1{{\tt % use \ttfamily in LaTeX
\string#1:
\begingroup\escapechar=-1 \expandafter\endgroup
\expandafter\meaning\csname\string#1\endcsname
}}

\catcode@=11 % \makeatletter in LaTeX
\def\MacroNameWith@InIt#1{whatever}
\catcode@=12 % \makeatother in LaTeX

\whatis{\sqrt}

\whatis{\MacroNameWith@InIt}% <-- braces are necessary!

\bye


You can easily turn this into LaTeX, if you prefer.

If you are sure the \whatis macro is never the argument to another command, you can do (LaTeX assumed)

\newcommand\whatis{\begingroup\makeatletter\whatisaux}
\newcommand\whatisaux[1]{\ttfamily\string#1: \meaning#1\endgroup}
`