我有以下代码
\begin{document}
\newcommand{\spec}[2][]{\sigma_{#1}\left(#2\right)}
\newcounter{i}%
\newtoks\striche%
\newcommand{\commu}[2][1]{%
\setcounter{i}{1}%
\striche={'}%
\loop%
\ifnum\value{i}<#1%
\striche=\expandafter{\the\expandafter\striche'}%
\stepcounter{i}%
\repeat%
{#2}\the\striche%
}
$\spec[\commu[2]{C}]{x}$
\end{document}
我收到错误消息argument of \\commu has an extra }
。两个宏单独运行正常。我发现
\spec[\commu{C}]{x}
确实有效。所以问题似乎出在 的可选参数上\commu
。有没有办法堆叠两个带有可选参数的宏?或者我做错了什么?
答案1
问题是你[]
在里面使用了[]
。要向 tex 隐藏这一点,你可以将宏包装在一组额外的中{}
:
\documentclass{article}
\begin{document}
\newcommand{\spec}[2][]{\sigma_{#1}\left(#2\right)}
\newcounter{i}%
\newtoks\striche%
\newcommand{\commu}[2][1]{%
\setcounter{i}{1}%
\striche={'}%
\loop%
\ifnum\value{i}<#1%
\striche=\expandafter{\the\expandafter\striche'}%
\stepcounter{i}%
\repeat%
{#2}\the\striche%
}
$\spec[{\commu[2]{C}}]{x}$
\end{document}
答案2
打字\spec[{\commu[2]{C}}]{x}
可以解决问题,但我认为您可以使用不同的解决方案xparse
,这可以解决一些其他小问题。
我做了两处调整:首先删除\left
,\right
其唯一的效果是在括号前后添加不需要的水平空间;其次,仅当存在下标时才添加下标。
没有下标和空下标之间是有区别的;在后一种情况下,TeX 会添加一个大小为\scriptspace
(默认值为 0.5pt)的水平空间;在示例中,我将其设置得非常大以显示会发生什么。0.5pt 的长度很小,但存在时会很明显。
定义的语法\spec
是它有一个可选参数o
和一个强制参数。如果后面的输入中存在可选参数,则条件\IfValueT
为真,并使用相关标记(它是 的简写\IfValueTF{_{#1}}{}
,这里在 false 情况下我们什么也不做)。
在 的定义中\commu
,可选参数的默认值为 1,因此表示为O{1}
。
使用expl3
(基于此xparse
)循环可以大大简化。
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\spec}{om}{%
\sigma
\IfValueT{#1}{_{#1}}%
(#2)%
}
\ExplSyntaxOn % we need to access lower level functions; here spaces are ignored
\NewDocumentCommand{\commu}{O{1}m}
{
#2\prg_replicate:nn { #1 } { ' }
}
\ExplSyntaxOff
\begin{document}
$\spec[\commu[2]{C}]{x}$ % no braces required
\bigskip
% let's show why \IfValueT is necessary
\setlength{\scriptspace}{20pt}
$\spec{x}$
$\sigma_{}(x)$ % what you'd get without the trick
\end{document}
请注意,这里不需要额外的括号。