1

I often want to define a command (using xparse) like the following

\NewDocumentCommand{\Comon}{oo}{
    \IfNoValueTF{#1}{
        \mathsf{Mod}
    }{
        \IfNoValueTF{#2}{
            \mathsf{Mod}_{#1}
        }{
            \mathsf{Mod}_{#1}(#2)
        }
    }
}

so that the same command name \Mod with different numbers of optional arguments displays differently.

Ideally, I'd be able to write my own command \NewCommandAlts which would be called like

\NewCommandAlts{\Mod}{2}
    {\mathsf{Mod}}
    {\mathsf{Mod}_{#1}}
    {\mathsf{Mod}_{#1}(#2)}

and would define a command \Mod that is equivalent to the one defined above.

The best that I have is

\newcommand{\NewCommandAltsTwo}[4]{
    \NewDocumentCommand{#1}{oo}{
        \IfNoValueTF{##1}{#2}{\IfNoValueTF{##2}{#3}{#4}}
    }
}

\NewCommandAltsTwo{\Mod}
    {\mathsf{Mod}}
    {\mathsf{Mod}_{#1}}
    {\mathsf{Mod}_{#1}(#2)}

which works. Any ideas for how to write the case that handles any number of arguments?

8
  • Your code compiles, the issue lies elsewhere in the document you tested it in.
    – Skillmon
    Jun 28, 2022 at 18:11
  • are you sure you want more than two optional arguments? even two is hard to use \Mod[a][b][c][d] is impossible to read and you can't not supply a if you want to supply d, at that stage it's better to use a different syntax such as \mod[field=2, value=42, whatever=something,...] Jun 28, 2022 at 18:22
  • 1
    @DavidCarlisle There is a simple remedy to this problem: you can simply alter the function signature to add otherwise ignored mandatory arguments in-between: \Mod[a]{}[b]{}[c]{}[d]. ;-))
    – frougon
    Jun 28, 2022 at 18:33
  • You can also use different delimiters like \NewDocumentCommand\splat{d<> o}... \splat<one>[two].
    – Rmano
    Jun 28, 2022 at 19:20
  • @Rmano that's highly discouraged syntax :P
    – Skillmon
    Jun 28, 2022 at 19:31

1 Answer 1

1

As long as the k-th optional argument is specified only in case the previous (k-1) optional arguments were specified, too, you can do something like this:

\newcommand\Firstoftwo[2]{#1}%
\newcommand\Secondoftwo[2]{#2}%
\newcommand\NewCommandAlts[2]{%
  \ifcat$\detokenize\expandafter{\Firstoftwo#2{}{}}$\expandafter\Firstoftwo\else\expandafter\Secondoftwo\fi
  {\NewDocumentCommand{#1}{}{}}%
  {\NewCommandAltsReverseLoop{0}{#1}{}{}#2{}{}\NewCommandAlts{}}%
}%
\csname @ifdefinable\endcsname\NewCommandAltsReverseLoop{%
  \long\def\NewCommandAltsReverseLoop#1#2#3#4#5#6\NewCommandAlts#7{%
    %#1 amount of items processed so far.
    %#2 command to define
    %#3 o-collection
    %#4 reversed list
    %#5 this item
    %#6 remaining items
    %#7 array of argument-numbers.
    \ifcat$\detokenize\expandafter{\Firstoftwo#6{}{}}$\expandafter\Firstoftwo\else\expandafter\Secondoftwo\fi
    {%
      \expandafter\NewCommandAltsLoop\expandafter{\Firstoftwo{}#3}{#2}{}#4{}{}\NewCommandAlts{0}#7\NewCommandAlts
    }{%
      \expandafter\NewCommandAltsReverseLoop\expandafter{\number\numexpr#1+1\relax}{#2}{#3o}{{#5}#4}#6\NewCommandAlts{{#1}#7}%
    }%
  }%
}%
\csname @ifdefinable\endcsname\NewCommandAltsLoop{%
  \long\def\NewCommandAltsLoop#1#2#3#4#5\NewCommandAlts#6#7\NewCommandAlts{%
    %#1 o-collection
    %#2 command to define
    %#3 result
    %#4 this item
    %#5 remaining items
    %#6 this argument number
    %#7 remaining argument-numbers
    \ifcat$\detokenize{#5}$\expandafter\Firstoftwo\else\expandafter\Secondoftwo\fi
    {%
      \NewDocumentCommand{#2}{#1}{#3}%
    }{%
      \ifnum#6=0 \expandafter\Firstoftwo\else\expandafter\Secondoftwo\fi
      {%
        \NewCommandAltsLoop{#1}{#2}{#4#3}#5\NewCommandAlts#7\NewCommandAlts
      }{%
        \NewCommandAltsLoop{#1}{#2}{\IfNoValueTF{###6}{#4}{#3}}#5\NewCommandAlts#7\NewCommandAlts
      }%
    }%
  }%
}%
\NewCommandAlts{\Mod}{%
    {\mathsf{Mod}} % Tokens in case no optional arguments
    {\mathsf{Mod}_{#1}} % Tokens in case one optional argument
    {\mathsf{Mod}_{#1}(#2)} % Tokens in case two optional arguments
    %{...} % Tokens in case three optional arguments
    %{...} % Tokens in case four optional arguments
    %{...} % Tokens in case five optional arguments
    %{...} % Tokens in case six optional arguments
    %{...} % Tokens in case seven optional arguments
    %{...} % Tokens in case eight optional arguments
    %{...} % Tokens in case nine optional arguments
}%

% \expandafter\show\csname Mod code\endcsname
% \ShowDocumentCommandArgSpec\Mod

\documentclass{article}
\begin{document}

$\Mod$

$\Mod[A]$

$\Mod[A][B]$

\end{document}

enter image description here

You must log in to answer this question.

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