[Tex/LaTex] How to \let an xparse defined command

expl3latex3macrosxparse

Let \example be an xparse defined command, which takes one optional and one mandatory argument. The definition of \example cannot be modified (e.g. because it comes from a third-party package).

The auhtor of \example forgot to handle an empty optional argument, so I want to patch it for my own use. The TeX-way would be to \let the original definition of \example to something else and use this backup in the redefinition.

This is not possible with LaTeX macros, which take an optional argument (but Heiko made letltxmacro for that). Also, this is not possible for xparse defined macros, because xparse wraps the actual definition into some very smart argument parser construct.

I made the following not working example, where I naively used \cs_new_eq:NN, which makes TeX go into an infinite loop (because \example is now calling itself recursively in the xparse logic).

\documentclass{article}
\usepackage{xparse}
\begin{document}

\ExplSyntaxOn
\NewDocumentCommand \example { o m }
 {
  #1 ~ #2
 }
\ExplSyntaxOff

\example[First]{Second}

\example{Second}

\ExplSyntaxOn
% This is obviously wrong
\cs_new_eq:NN \orig_example:wn \example

\RenewDocumentCommand \example { o m }
 {
  \IfValueTF { #1 }
   { \orig_example:wn [ #1 ] { #2 } }
   { \orig_example:wn { #2 } }
 }
\ExplSyntaxOff

\example[First]{Second}

\example{Second}

\end{document}

Best Answer

In general the answer is do not do this. The idea behind xparse is the document level commands (\example) are there to define the syntax but should be implemented by use of documented code-level functions (so something like \module_command:nn here). As such, any new or altered definitions should not pass 'document level' syntax around at all but should be defined using xparse and the code-level functions the original uses

\NewDocumentCommand \example { o m }
  {
    \module_command:nn {#1} {#2} % Oops, doesn't cover \NoValue
  }
...
\RenewDocumentCommand \example { o m }
  {
    \IfNoValueTF {#1}
      { \module_command:n {#2} } % Presumably different
      { \module_command:nn {#1} {#2} }
  }

As such, the team quite deliberately don't provide \LetDocumentCommand or similar.


The best practice for expl3 and xparse use has developed over some time and as such some packages written by the team themselves still need revision to follow them. From my own code, notes2bib is probably the 'model' package in terms of showing the correct approach. On the other hand, at the time of writing the release version of siunitx needs revision to follow them: the code was largely written in parallel with expl3 and xparse development. There is development ongoing to create a third version of siunitx which will be implemented with this clear separation. (I hope to get this ready during 2016.)

If you need to create a new interface for an xparse-defined command and it is built on non-documented code functions, at present you will have to use those

\RenewDocumentCommand \example { o m }
  {
    % To be revised once documented interfaces are available
    \IfNoValueTF {#1}
      { \__module_command:n {#2} } % Presumably different
      { \__module_command:nn {#1} {#2} }
  }

Most authors making use of expl3 are aware of this aim, but you might wish to check with them that such developments are ongoing.

Related Question