\newcommand 参数混淆

\newcommand 参数混淆

我正在努力解决LaTeX 初学者指南作者:Stefan Kottwitz。我被难住了:

\documentclass{article}
\newcommand{\keyword}[2][\bfseries]{{#1#2}}
\begin{document}
\keyword{Grouping} by curly braces limits the
\keyword{scope} of \keyword[\itshape]{declarations}.
\end{document}

输出结果将“Groupings”和“scope”加粗,而“declarations”则加斜体。我不明白这种语法。我隐约知道这\bfseries是“默认”的,并\itshape特意用“declarations”来代替,但我不明白 Kottwitz 的解释:

我们再看一下代码中加粗标记的行。通过使用[\bfseries],我们引入了一个可选参数。我们用 来引用它#1。它的默认值是\bfseries。由于我们这次使用了声明,因此我们添加了一对括号以确保只有关键字受到声明的影响。在文档的后面,我们给出了[\itshape]\keyword将默认格式更改为斜体。

我可以就此处发生的事情征询第二意见/解释吗?

答案1

语法\newcommand 没有可选参数如下:

\newcommand{<name>}[<args>]{ <code> }

其中<args>是参数的数量(范围从 1 到 9)。在<code>定义的部分中,每个参数都用一个#符号标记:因此第一个参数是,#1第二个参数是,#2等等。因此,如果我们创建一个\reverseconcat具有三个强制参数的宏并将它们以相反的顺序连接起来,我们将按如下方式定义它:

\newcommand{\reverseconcat}[3]{#3#2#1} % version 1

我们将按如下方式使用它:

\reverseconcat{A}{B}{C}

输出“CBA”

现在假设我们希望命令使输出变为粗体。为此,我们需要添加\bfseries代码。假设我们这样做:

\newcommand{\reverseconcat}[3]{\bfseries#3#2#1} % version 2

但是,如果我们将相同的参数传递给此命令,就会遇到一个问题:代码部分就像我们刚刚\bfseries CBA在文档中输入一样,并且由于是一个开关,它将使所有后续文本变为粗体,这不是我们想要的。因此,在这种情况下,我们需要通过在代码部分周围添加括号来\bfseries限制范围。\bfseries

\newcommand{\reverseconcat}[3]{{\bfseries#3#2#1}} % version 3

现在,当我们将相同的参数传递给此命令时,就好像我们{\bfseries CBA}在我们的文档中输入了内容一样,这正是我们想要的。

现在假设我们希望命令有一个可选参数。根据定义,可选参数是总是指定的参数#1(即第一个参数)。但是,由于即使用户省略了第一个参数,命令仍然具有第一个参数,因此我们仍然需要为其提供一个值。因此命令的语法发生了变化:

\newcommand{<name>}[<args>][<first argument value>]{<code>} 

现在让我们让反向连接宏接受一个可选参数,该参数指定如何格式化反转的文本。在这种情况下,我们的新宏将接受参数(假设我们仍然想要我们最初的 3 个参数。)

因此我们的新命令如下所示:

\newcommand{\reverseconcat}[4][\bfseries]{{#1#4#3#2}}

此宏的行为与上面的版本 3 完全相同,因此\reverseconcat{A}{B}{C}将输出“篮球联赛“。但是请注意,由于我们添加了可选参数,因此用于反转部分的数字是不同的:它们从 开始,#2因为#1是可选参数。

但是,我们的新命令允许我们为第一个参数指定不同的值,因此,如果我们不希望文本变为粗体,我们可以通过将\itshape其变为斜体:

\reverseconcat[\itshape]{A}{B}{C}

这将产生“篮球联赛

正如 Przemysław Scherwentke 在他的回答中所说,你实际上可以将任何内容传递给这个命令,而不仅仅是格式化命令,所以,例如,如果你忘记了\on \itshape

\reverseconcat[itshape]{A}{B}{C}

输出将是“itshapeCBA”

最后这个例子表明,期望用户将一个命令传递给另一个命令可能不是最好的主意,因为您希望上面的示例产生错误而不是产生不正确的输出。但在这里解决这个问题会让我们走得太远。

答案2

这里有两个独立的事情,我认为同时处理它们可能会造成混乱。第一件事是可选参数第二件事是用于限定范围的括号

可选参数

当你定义一个命令时

\newcommand\isgreat[2]{#1 thinks #2 is great.}

你在定义周围加上{和。然后出现的就会像你期望的那样被替换:}\isgreat

\isgreat{John}{Stack Exchange} He uses it every day.

John 认为 Stack Exchange 很棒。他每天都会使用它。

如果你这样写:

\newcommand\isgreat[2][John]{#1 thinks #2 is great.}

那么第一个参数是可选的。如果你给它,它默认为John

\isgreat{LaTeX}

约翰认为 LaTeX 很棒。

如果你给它,你必须把它放在方括号中。

\isgreat[Gary]{LaTeX}

Gary 认为 LaTeX 很棒。

用于限定范围的括号

当您书写时\bfseries,就像单击 Microsoft Word 中的“粗体”工具栏按钮一样——从那时起您键入的所有内容都将变为粗体。

John thinks LaTeX is \bfseries great. He uses it every day.

John 认为 LaTeX 是太棒了。他每天都用它。

为了将粗体限制在文本的特定部分,可以将其括在括号中。

John thinks LaTeX is {\bfseries great}. He uses it every day.

John 认为 LaTeX 是伟大的。他每天都用它。

最后

在 Stefan 的例子中,LaTeX 取代了

\keyword{Grouping} by curly braces

{\bfseries Grouping} by curly braces

您知道为什么需要额外的花括号吗\newcommand?一对花括号用于提供定义,另一对花括号用于限制命令的范围\bfseries

答案3

\newcommand{\keyword}[2][\bfseries]{{#1#2}}是一个具有 2 个参数和一个可选参数的宏。如果未指定,\bfseries则将其作为第一个参数。如果您写入,例如,\keyword[AAA]{declarations}您将获得AAAdeclarations罗马字体。

答案4

我认为令人费解的部分,正如在约翰的回答,是这句话

由于我们这次使用了声明,所以我们添加了一对括号以确保只有关键字受到声明的影响。

引用声明可能会与与宣言一个新的命令。

相反,它指的是\newcommand内容的扩展不会自动限定范围,并且在使用\bfseries和其他声明的特定情况下,您必须自己处理范围,通过让最后一个参数newcommand限定范围:{#1#2}而不是#1#2

也许从不同的例子开始会有所帮助:

\documentclass{article}
\newcommand{\dummy}[2][0]{#2^#1}
\begin{document}

the default is $\dummy{A}$ but you can switch to $\dummy[2]{A}$

\end{document}

相关内容