# Expanding command with optional arguments: \edef

I have defined a LaTeX command with an optional argument, e.g., \newcommand*{\commA}[1][opt]{A#1}, and I cannot get it to be part of an expanded command defintion with \edef, e.g., \edef\expcom{\commA}.

I have tried different combinations to find out what is going on: first, if I define the command \commA without optional arguments, the code compiles smoothly. Second, if I leave \commA definition with optional arguments, but I define \expcom with \def, the code compiles smoothly, too. Thus, It is only the combination of optional argument definition and \edef that it is faulty.

How can I pass a command with optional arguments to a \edef definition?

See example of buggy code

\documentclass{article}

\begin{document}

%\newcommand*{\commA}{A} %This definition gives no error
\newcommand*{\commA}[1][opt]{A#1} %This definition raises error "! Argument of \reserved@a has an extra }."

\edef\expcomm{\commA}
%\def\expcomm{\commA} %The definition with \def gives no error
\def\noexpcomm{\commA}

\noindent
This is \verb|\expcomm|: \expcomm\\
This is \verb|\noexpcomm|; \noexpcomm\\

\renewcommand*{\commA}{B}

\noindent
This is \verb|\expcomm|: \expcomm\\
This is \verb|\noexpcomm|; \noexpcomm\\

\end{document}


The output I would expect with the \commA definition with optional argument is following:

When I use the \commA definition without optional argument I get following, as expected:

• Commands with an optional argument don't survive \edef. Please, tell us what you really want to achieve, unless this is just an academic question. Jun 28, 2021 at 9:03
• you can't such a \newcommand is not expandable. Jun 28, 2021 at 9:04
• ...and if you try \NewExpandableDocumentCommand\commA{O{opt}}{A#1} the new kernel will happily inform you that LaTeX cmd Error: Argument specification 'O{opt}' for expandable command '\commA' ends with optional argument. ... so I suppose it can't be done. Jun 28, 2021 at 9:06
• @egreg, (at)ulrike, (at)Rmano. Okay, thanks for ultra quick answer. Leave it like that. The certain knowledge that I cannot expand a command with optional arguments is already an achievement for me (sigh). I am in amidst of a complicated code and I cannot summarize in two words what I am trying to achive, but If I get to, I'll surely ask. Jun 28, 2021 at 9:09
• You can expand a command with optional argument(s) if the last argument is not optional... Jun 28, 2021 at 9:22

You can get an expandable command with optional arguments provided

1. the optional arguments are followed by a mandatory one;
2. you use \NewExpandableDocumentCommand. (For LaTeX release before 2020-10-01 include the xparse package)

So with

\NewExpandableDocumentCommand{\commA}{O{opt}m}{A#1}


you can call

\edef\expcommA{\commA{}}
\edef\expcommB{\commA[new]{}}


Note the dummy mandatory argument.

Full test document:

\documentclass{article}

\NewExpandableDocumentCommand{\commA}{O{opt}m}{A#1}

\begin{document}

\edef\expcommA{\commA{}}
\edef\expcommB{\commA[new]{}}

\texttt{\meaning\expcommA}

\texttt{\meaning\expcommB}

\end{document}


I believe this is a typical XY problem, though.

• It was, doubtless, an XY problem; in the meanwhile I found an alternative fix (not really clean) without having to expand the macro with optional argument, however, this was the first possible solution I came across ´:). I am sure, someone else is gonna benefit from this contribution. Jun 28, 2021 at 10:30

In case it doesn't matter if \commA is not replaced by its replacement-text during the \edef you can use \protected@edef for having expanding \commA suppressed while having the tokens forming its optional argument expanded if provided.

\documentclass{article}

\begin{document}

\newcommand*{\commA}[1][opt]{A#1} %This definition raises error "! Argument of \reserved@a has an extra }."

\csname protected@edef\endcsname\expcomm{\commA}

\noindent This is \verb|\expcomm|: \texttt{\meaning\expcomm}

\newcommand\foobar{expansion of \string\foobar}
\csname protected@edef\endcsname\expcommOptionalArgExpanded{\commA[\foobar]}

\noindent This is \verb|\expcommOptionalArgExpanded|: \texttt{\meaning\expcommOptionalArgExpanded}

\end{document}


But in your case it seems to matter as in your question you have \commA redefined somewhere in the middle of your example...