LaTeX's protection mechanism only protects the macro, not its arguments. In LaTeX macro can be used/executed in different contexts:
Normal typesetting context (\set@typeset@protect).
\protect has the meaning of \relax. It does not touch the following
macro which is executed normally.
Display context (\set@display@protect).
Macros are displayed inside messages, errors, warnings, or \typeout. \protect becomes \string that converts the following macro into simple character tokens that cannot be executed anymore.
Expansion context (\@unexpandable@protect).
\protect is \noexpand here that prevents the following macro from the next expansion.
\string and \noexpand only affects the next token. They do not protect whole arguments with many tokens. Nowadays most TeX engines support e-TeX, which comes with \detokenize and \unexpanded. Both work on token lists and can be used to protect arguments.
To some degree the definition of \aaaa can be extended to support the protection of its argument, e.g.:
\documentclass{article}
\makeatletter
\newcommand*{\aaaa}{%
\ifx\protect\@typeset@protect
\csname aaaa \expandafter\endcsname
\else
\ifx\protect\@unexpandable@protect
\protect@unexpand@cmd@arg\aaaa
\else
\ifx\protect\string
\protect@string@cmd@arg\aaaa
\else
\expandafter\protect@unknown@cmd@arg
\csname aaaa \endcsname
\fi
\fi
\fi
}
\expandafter\newcommand\csname aaaa \endcsname[1]{%
\begingroup
\def\bbbb{bbbb}%
#1%
\endgroup
}
% unexpanded protect
\def\protect@unexpand@cmd@arg#1\else#2\fi\fi\fi#3{%
\fi\fi
\ifx\thepage\relax
\detokenize
\else
\unexpanded
\fi
{#1{#3}}%
}
% display protect
\def\protect@string@cmd@arg#1\else#2\fi\fi\fi#3{%
\fi\fi\fi
\detokenize{#1{#3}}%
}
% unknown protect
\def\protect@unknown@cmd@arg#1\fi\fi\fi{%
\fi\fi\fi
\protect#1%
}
\makeatother
\begin{document}
\listoffigures
% test typeset context
\aaaa{\bbbb}
%
\makeatletter
\protected@edef\x{\aaaa{\bbbb}}
\typeout{\meaning\x}
\makeatother
\typeout{\aaaa{\bbbb}}
\begin{figure}
\caption{long \aaaa{\bbbb}}
\end{figure}
\end{document}
However a serious problem remains with deferred writing, which is used for the index, for example. If an index entry is written, \thepage is prevented from expanding; the write node will therefore contain the macro \thepage instead of the current page number and may thus be wrong. At shipout time, the write node expands its contents and flushes it to the file. At this time the page number is known and \thepage expands to the right page number.
Unfortunately this causes an ambiguity for \aaaa:
If it is written to a file, then it should use \detokenize for itself and its argument to prevent any early expansions.
It should use \unexpanded if it is used inside a macro definition by \protected@edef and the macro is not written to a file, but executed later.
Unfortunately there is no safe and robust method to distinguish both cases from inside the macro \aaaa.
The example above uses a heuristics and assumes that if \thepage is disabled from expansion (via \let\thepage\relax), then the macro is probably written to a file.
\bbbbdoesn't exist when you call\caption. One way to avoid premature expansion is to use\aaaa{\protect\bbbb}. – Werner Feb 13 '14 at 19:17\aaaa's argument should only be expanded by\aaaaitself and\captionshould not alter it in any way. – mh543 Feb 13 '14 at 19:55\protectcertain components that you want to not expand, since\captiondoes some legwork in the background to check for the size/width of the caption and whether or not to center/justify it. – Werner Feb 13 '14 at 20:13\captionneeds to do some legwork. However, shouldn't it expand \aaaa instead? By touching\bbbbwithout\aaaa's context, it will never get the right size. – mh543 Feb 14 '14 at 23:10mhchempackage. This package defines the\cecommand that uses a special syntax for its argument. Part of this syntax is the\bondcommand.\ce's argument should only be parsed by\ce, because it doesn't make sense otherwise. However, the\captioncommand tries to expand\ce's argument independently from\ce. This cannot lead to anything sensible and I would like to avoid this. (The problem became visible when the author removed a global definition of\bondand put it in the local context of\ce.) – mh543 Feb 14 '14 at 23:22\ce? This would make the problem much clearer. – egreg Feb 18 '14 at 00:16