我使用一些有效但不可靠的\def
魔法来减少与数学指标有关的样板。(这是在 LaTeX 中,但我想不出使用它的方法newcommand
)。
\makeatletter
\def\@subarg[#1]{_{\rm #1}}
\def\Lam{{\Lambda}\@ifnextchar[\@subarg{}}
\def\Reg{{\cal R}\@ifnextchar[\@subarg{}}
% .
% .
% many similar definitions
% .
% .
\makeatother
这个想法是,当我说 时\Lam[frog]
,\@subarg@
宏会吞噬可选参数并将其放入罗马字母中。如果我不想要罗马字母下标,我仍然可以像往常一样执行\Lam
和\Lam_k
。
所有这些都能正常工作,但不太可靠。很抱歉,我无法很好地描述错误,但我知道章节标题存在问题。
\subsubsection{Start $\Lam[fee] fi$ fo }
\subsubsection{Start $\Lam[fee] fi$ }
\subsubsection{Start $\Lam[fee]$ }
全部生成! Missing \endcsname inserted.
虽然
\subsubsection{Start $\Lam$ }
\subsubsection{Start $\Lam$}
产生:! Argument of \@sect has an extra }.
有人知道如何让宏更加健壮吗?
答案1
您面临的问题之所以会逐渐出现,是因为您将内容插入到了一个脆弱的宏(一个分段单元)中。这个分段单元不仅发送要设置的内容,还会发送 ToC,这就是您遇到问题的地方。
解决这个问题的一种方法是,\protect
在分段单元中使用宏时实际使用它们(例如,\protect\Lam...
)。或者,你会问“如何使它们更强大?”好吧,使用\DeclareRobustCommand
!
\documentclass{article}
\makeatletter
\def\@subarg[#1]{_{\mathrm{#1}}}
\DeclareRobustCommand\Lam{\Lambda\@ifnextchar[\@subarg{}}
\DeclareRobustCommand\Reg{\mathcal{R}\@ifnextchar[\@subarg{}}
\makeatother
\begin{document}
\section{Start $\Lam[fee] fi$ fo}
\section{Start $\Lam[fee] fi$}
\section{Start $\Lam[fee]$}
\end{document}
答案2
\@ifnextchar
当有更高级别的工具可用时,您应该避免使用;对于您的情况,我会使用\newcommand
:
\newcommand{\Lam}[1][]{%
\Lambda
\if\relax\detokenize{#1}\relax % test if the optional argument is empty
% do nothing
\else
_\textnormal{#1}
\fi
}
这不会引发您正在实验的脆弱性问题,因为具有定义的可选参数的命令\newcommand
是强大的。
当然,输入多段类似的代码很烦人,甚至是错误的。所以我们可以定义一个 catch all 宏:
\documentclass{article}
\usepackage{amsmath}
\newcommand{\definevariable}[2]{% #1 = macro, #2 = actual variable
\newcommand{#1}{#2\definevariabletestargument}%
}
\newcommand\definevariabletestargument[1][]{%
\if\relax\detokenize{#1}\relax % test if the optional argument is empty
% do nothing
\else
_\textnormal{#1}%
\fi
}
\definevariable{\Lam}{\Lambda}
\definevariable{\Reg}{\mathcal{R}}
\begin{document}
\section{Here we have $\Reg$}
\subsection{With subscript $\Reg[xy]$}
\subsection{And $\Lam$}
\subsection{With subscript $\Lam[fee]$}
\end{document}
请注意使用\textnormal
而不是\mathrm
,例如,它允许在输入中留有空格。
一个更强大的工具是xparse
:
\documentclass{article}
\usepackage{amsmath,xparse}
\NewDocumentCommand{\definevariable}{mm}{% #1 = macro, #2 = actual variable
\NewDocumentCommand{#1}{o}{%
#2%
\IfValueT{##1}{_\textnormal{##1}}%
}%
}
\definevariable{\Lam}{\Lambda}
\definevariable{\Reg}{\mathcal{R}}
\begin{document}
\section{Here we have $\Reg$}
\subsection{With subscript $\Reg[xy]$}
\subsection{And $\Lam$}
\subsection{With subscript $\Lam[fee]$}
\end{document}