使用 xparse 传递 * 参数

使用 xparse 传递 * 参数

xparse想要定义一个命令 Command-One,它会调用一个命令 Command-Tw​​o,并且当且仅当调用了 Command-One 的 *ed 版本时才会调用 *ed 版本。

具体来说,我想做类似的事情:

\DeclareDocumentCommand{\CTwo}{s o m}
{\IfBooleanTF{#1}{#2}{#3}}

\DeclareDocumentCommand{\CTest}{s o}
{\CTwo#1[#2]{testing}}

\CTest*[work]

并让其输出“work”。

我意识到我可以这样做

\DeclareDocumentCommand{\CTest}{s o}
{\IfBooleanTF{#1}
  {\CTwo*[#2]{testing}}
  {\CTwo[#2]{testing}}}

但这不够优雅,而且我将定义几个不同的命令,每个命令都有不同的#3in值\CTwo,而且总是需要多次复制 If-Then 语句(以及必须复制两次特定参数)


以下是使用环境的更详细示例。具体来说,我希望能够定义一个环境模板,然后只需向其传递参数即可使用它来定义几个不同的环境。

\documentclass{amsart}
\usepackage{amsthm}
\usepackage{xparse, l3fp,l3tl}
\begin{document}

\ExplSyntaxOn
\def\TheoremDepth{section}
\theoremstyle{plain}
\newtheorem{theorem}{Theorem}[\TheoremDepth]%
\newtheorem*{theoremstar}{Theorem}%

\DeclareDocumentEnvironment{TheoremTemplate}{s o m m}
{
\IfBooleanTF{#1}
    { Do something
    \begin{#1}}
    { Do something else
    \begin{#2} }
    }
{
\IfBooleanTF{#1}
    { Do something
    \end{#1}}
    { Do something else
    \end{#2} }
}

\DeclareDocumentEnvironment{MyTheorem}{s o}
{
\begin{TheoremTemplate}#1[#2]{theorem}{theoremstar}
}
{
\end{TheoremTemplate}
}
\ExplSyntaxOff
\end{document}

然后我希望能够调用 \begin{theorem} 和 \begin{theorem}* 并让它们做相应的事情。

答案1

我的印象是你使用了错误的方法;此外,这\begin{theorem}*似乎不是最好的语法。

\documentclass{article}
\usepackage{xparse,amsthm}

\NewDocumentCommand{\DeclareTheorem}{momo}{%
 % #1=environment's name
 % #2=sibling counter
 % #3=label
 % #4=parent counter
 \IfNoValueTF{#4}
  {%
   \IfNoValueTF{#2}
    {\newtheorem{#1}{#3}}
    {\newtheorem{#1}[#2]{#3}}%
  }
  {%
   \newtheorem{#1}{#3}[#4]%
  }
 \newtheorem*{#1*}{#3}
}

\theoremstyle{plain}
\DeclareTheorem{thm}{Theorem}[section]
\DeclareTheorem{lem}[thm]{Lemma}

\begin{document}

\section{Test}

\begin{lem}
Numbered.
\end{lem}

\begin{thm}
This is numbered.
\end{thm}

\begin{lem*}
Unnumbered.
\end{lem*}

\begin{thm*}
This is unnumbered.
\end{thm*}

\end{document}

在此处输入图片描述

如果你希望定理默认按照章节或节进行编号,你可以将该\NewDocumentCommand行更改为

\NewDocumentCommand{\DeclareTheorem}{momO{\TheoremDepth}}{%

给出适当的定义\TheoremDepth;在这种情况下,上面的声明将变成

\DeclareTheorem{thm}{Theorem}
\DeclareTheorem{lem}[thm]{Lemma}

如果\TheoremDepth被定义为section

答案2

为了扩展我的评论,我有几个假设。为什么\CTest需要调用\CTwo?如果\CTest采用可选参数,为什么需要星号来指示是否使用它?\CTest如果没有可选参数,应该如何表现?

通常(按照expl3惯例),你会定义一个具有固定数量参数的底层函数,该函数在处理可选参数后接受你的输入,依此类推。为了简化示例(也许会降低复杂性,但我希望你能理解),你可以编写如下代码:

\documentclass{article}
\usepackage{xparse}
\begin{document}
\ExplSyntaxOn
\cs_new:Nn \my_output:n {#1}

\DeclareDocumentCommand{\CTest}{s O{testing}}
  {
    \IfBooleanTF{#1}
      { \my_output:n {#2} }
      { \my_output:n {testing} }
  }
\ExplSyntaxOff

\CTest\\
\CTest*\\
\CTest[work]\\
\CTest*[work]\\

\end{document} 

因为您似乎有两种应该使用默认值的情况(当不存在星号时,以及当不存在参数时),所以需要在两个地方输入此默认值。

您可能还希望有类似您\CTwo定义的单独调用此\my_output:n命令的功能。如果这不能体现您要执行的操作的复杂性,我建议您澄清您的问题。

相关内容