1

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: enter image description here

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

enter image description here

6
  • 1
    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.
    – egreg
    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.
    – Rmano
    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
  • 1
    You can expand a command with optional argument(s) if the last argument is not optional... Jun 28, 2021 at 9:22

2 Answers 2

1

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}

enter image description here

I believe this is a typical XY problem, though.

1
  • 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
0

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}

enter image description here

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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .