2

I created a command with 3 optional arguments.

Here is a MWE:

\documentclass[10pt,a4paper,french]{article}

\usepackage{mathtools}
\usepackage{babel}
\usepackage[warnings-off={mathtools-colon,mathtools-overbracket},math-style=french]{unicode-math}
\usepackage[scale={0.75,0.8},footskip=1.5cm,heightrounded]{geometry}

\NewDocumentCommand{\pliste}{O{x} O{1} O{n}}{(#1_{#2},\dotsc,#1_{#3})}


\begin{document}        
    $\pliste$,\quad$\pliste[y]$,\quad$\pliste[z][2]$,\quad$\pliste[a][][p]$
\end{document}

It works fine but in the case $\pliste[a][][p]$, the default value (1, here) doesn't appear for the second argument. So maybe it is not a good idea to only have optional arguments? Am I doing anything wrong?

3
  • 4
    Using an empty optional argument is not the same as not using the optional argument. So if you want to replace an empty argument by a default value, you also have to test for an empty argument inside the definition of \pliste.
    – cabohah
    Commented Jul 6, 2023 at 6:28
  • 1
    generally it's a bad idea to have consecutive optional arguments (whether or not there are additional mandatory arguments) as, as you show, it's not possible to omit earlier ones without omiting the later ones Commented Jul 6, 2023 at 7:40
  • Thank you to both of you. I will change the definition of my macro
    – Didier
    Commented Jul 6, 2023 at 13:21

2 Answers 2

4

The default argument is inserted only when the optional argument is not specified. Specifying [] means that the optional argument will be replaced by nothing.

Optional arguments are not a problem, the bad idea is to use multiple ones when they're independent of each other.

To make an example, \makebox has two optional initial arguments, but the second one only makes sense if the first one is specified:

\makebox{x}% natural width
\makebox[2cm]{x}% 2cm wide (centered by default)
\makebox[2cm][l]{x}% 2cm wide left aligned

The following sort of works

\documentclass[10pt,a4paper]{article}
\usepackage{mathtools}

\NewDocumentCommand{\pliste}{O{x} O{1} O{n}}{%
  (\IfBlankTF{#1}{x}{#1}_{\IfBlankTF{#2}{1}{#2}},\dots,\IfBlankTF{#1}{x}{#1}_{#3})%
}

\begin{document}

$\pliste$,
$\pliste[y]$,
$\pliste[z][2]$,
$\pliste[a][][p]$

\end{document}

but it's really awkward.

enter image description here

You might make the variable name mandatory and change the order of the optional arguments:

\documentclass[10pt,a4paper]{article}
\usepackage{mathtools}

\NewDocumentCommand{\pliste}{O{1} m O{n}}{(#2_{#1},\dots,#2_{#3})}

\begin{document}

$\pliste{x}$,
$\pliste[2]{y}$,
$\pliste{z}[p]$,
$\pliste[2]{a}[p]$

\end{document}

enter image description here

The same output can be generated with a different approach, where there's a single (optional) argument that accepts key-value syntax.

\documentclass[10pt,a4paper]{article}

\usepackage{mathtools}

\ExplSyntaxOn

\keys_define:nn { didier/pliste }
 {
  v .tl_set:N = \l_didier_pliste_variable_tl,
  s .tl_set:N = \l_didier_pliste_start_tl,
  e .tl_set:N = \l_didier_pliste_end_tl,
 }
% defaults
\tl_new:N \l_didier_pliste_initial_tl
\keys_precompile:nnN { didier/pliste } { v=x, s=1, e=n } \l_didier_pliste_initial_tl

\NewDocumentCommand{\pliste}{O{}}
 {
  \group_begin:
  \tl_use:N \l_didier_pliste_initial_tl
  \keys_set:nn { didier/pliste } { #1 }
  (
  \l_didier_pliste_variable_tl\sb{\l_didier_pliste_start_tl}
  ,\dots,
  \l_didier_pliste_variable_tl\sb{\l_didier_pliste_end_tl}
  )
  \group_end:
 }

\ExplSyntaxOff

\begin{document}        

$\pliste$,
$\pliste[v=y,s=2]$,
$\pliste[e=p,v=z]$,
$\pliste[s=2,v=a,e=p]$

\end{document}

The advantage here is that you don't need to recall the order of the arguments, but just the key names, here

  • v for “variable”
  • s for “start”
  • e for “end”

As an aside, if \dots is followed by a comma, then amsmath automatically uses \dotsc. This command is mainly thought to be used when it's not possible to guess the following character, say

$x_{1},x_{2},\dots,x_{n},x_{n+1},\dotsc$
1
  • Thank you @egreg for this very complete answer. I understand better your first solution. I never heard about ´\ExplSyntaxOn´, so I will see what I can find about it
    – Didier
    Commented Jul 6, 2023 at 13:25
1

I agree with @egreg that this should be avoided, but just for the sake of it, this shows another possibility using ltcmd's argument processors. The idea is pretty simple, just set them as empty by default, and use the argument processor to change them to their true defaults if they are empty/blank.

\documentclass{article}

\usepackage{mathtools}

\newcommand\ProcessOdefault[2]
  {%
    \IfBlankTF{#2}
      {\edef\ProcessedArgument{\unexpanded{#1}}}
      {\edef\ProcessedArgument{\unexpanded{#2}}}%
  }

\NewDocumentCommand{\pliste}
  {>{\ProcessOdefault{x}}O{} >{\ProcessOdefault{1}}O{} O{n}}
  {(#1_{#2},\dotsc,#1_{#3})}


\begin{document}        
    $\pliste$,\quad$\pliste[y]$,\quad$\pliste[z][2]$,\quad$\pliste[a][][p]$
\end{document}

Another possibility is to insert otherwise unused optional stars, with those you can jump over the unneeded optional arguments if necessary:

\documentclass{article}

\usepackage{mathtools}

\NewDocumentCommand{\pliste}
  {O{x} s O{1} s O{n}}
  {(#1_{#3},\dotsc,#1_{#5})}


\begin{document}        
    $\pliste$,\quad$\pliste[y]$,\quad$\pliste*[2]$,\quad$\pliste[a]*[p]$,\quad$\pliste**[p]$
\end{document}

You must log in to answer this question.

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