How to make @ a letter within a macro

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} 

enter image description here


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}

Comments on the original approach:

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).


\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.

enter image description here

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}

Tags:

Macros