NewDocumentCommand 仅带有可选参数?

NewDocumentCommand 仅带有可选参数?

我创建了一个带有 3 个可选参数的命令。

以下是 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}

它运行正常,但在这种情况下$\pliste[a][][p]$,第二个参数的默认值(此处为 1)没有出现。所以也许只使用可选参数不是一个好主意?我做错了什么吗?

答案1

插入默认参数仅有的当未指定可选参数时。指定[]意味着可选参数将被替换为空。

可选参数不是问题,坏主意是在它们彼此独立时使用多个参数。

举个例子,\makebox有两个可选的初始参数,但只有在指定第一个参数时第二个参数才有意义:

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

以下类型的作品

\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}

但这真的很尴尬。

在此处输入图片描述

您可以将变量名称设为必需的,并更改可选参数的顺序:

\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}

在此处输入图片描述

可以使用不同的方法生成相同的输出,其中有一个接受键值语法的单个(可选)参数。

\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}

这里的优点是,你不需要记住参数的顺序,而只需要记住键名称。

  • v“变量”
  • s“开始”
  • e代表“结束”

另外,如果\dots后面跟着逗号,则amsmath自动使用\dotsc。此命令主要被认为是在无法猜测以下字符时使用的,例如

$x_{1},x_{2},\dots,x_{n},x_{n+1},\dotsc$

答案2

我同意 @egreg 的观点,应该避免这种情况,但只是为了避免这种情况,这显示了使用 的ltcmd参数处理器的另一种可能性。这个想法很简单,只需默认将它们设置为空,如果它们是空的/空白的,则使用参数处理器将它们更改为真正的默认值。

\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}

另一种可能性是插入原本未使用的可选星号,必要时您可以跳过不需要的可选参数:

\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}

相关内容