You are trying to \edef
(\xdef
= \global\edef
) the macro \macom
. However, as \macom
is a command with an optional argument, this cannot be done safely. You need to either not do an \edef
, use the LaTeX protected mechanism:
\documentclass{article}
\begin{document}
\makeatletter
\newcommand{\createDATA}[1]{%
\xdef\DATA{}%
\newcommand{\test}[2][]{%
\protected@xdef\DATA{\DATA args=##1 , ##2 }%
}%
\test[x]{\macom[x]{blabla}}%
}
\makeatother
\newcommand{\macom}[2][q]{AAA}
\createDATA
\DATA
\end{document}
or make \macrom
engine robust using the e-TeX extensions, for example
\documentclass{article}
\usepackage{etoolbox}
\begin{document}
\newcommand{\createDATA}[1]{%
\xdef\DATA{}%
\newcommand{\test}[2][]{%
\xdef\DATA{\DATA args=##1 , ##2 }%
}%
\test[x]{\macom[x]{blabla}}%
}
\newrobustcmd{\macom}[2][q]{AAA}
\createDATA
\DATA
\end{document}
(By the way, you have a lot of extraneous spaces in your commands: I've added %
to kill line ends and deal with these.)
For more on what robust, protected and 'fragile' means, see What is the difference between Fragile and Robust commands?
The reason that you cannot \edef
a command with optional arguments is that these are picked up using the TeX primitive \futurelet
. This performs an assignment, and assignments are not expandable. On the other hand, grabbing a mandatory argument does not require any tricks, so it is expandable.
[It's a bit more complex than that, as there are ways of expandably testing for optional arguments. These are more restrictive than the non-expandable approach, and the LaTeX2e kernel therefore goes with comprehensive-but-non-expandable. For pre-constructed methods for both expandable and non-expandable optional argument grabbing, with automatically robust functions and lots of additional cleverness, see the LaTeX3 xparse
module.]
\xdef
. The error message is not quite informative, however.