子句只有两个\ifthenelse
——<then clause> 和 <clause>,如果需要两个以上的测试条件,就\ifthenelse
需要嵌套,这样代码就比较难维护了。有没有更好的办法,比如像这样的 switch-case 宏(类似 C 语言):
\switchconditon
{<case 1> <clause 1>}
{<case 2> <clause 2>}
{<case 3> <clause 3>}
例如\ifthenelse
:
\ifthenelse{\equal{#1}{ul}}%ul=upper left
{\let\position\AtPageUpperLeft}
{}
\ifthenelse{\equal{#1}{ll}}%ll=lower left
{\let\position\AtPageLowerLeft}
{}
\ifthenelse{\equal{#1}{pc}}%pc=paper center
{\let\position\AtPageCenter}
{}
您能给出实现最后一个代码功能的代码吗?谢谢。
答案1
LaTeX3 的编程expl3
层带有许多用于此类目的的实用函数。该模型提供了不同的数据结构和可对其进行操作的算法。其中一些有语句switch
,请参阅下面的示例。
对于您的用例来说,这\str_case:nn
是合适的。如果没有找到匹配项,则会发出错误信号。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\msg_new:nnn
{ switchcase }
{ no-match }
{ There~is~no~entry~`#1'~in~the~switch~statement! }
\NewDocumentCommand \switchcase { m m }
{
\str_case:nnF { #1 } { #2 } { \msg_error:nnn { switchcase } { no-match } { #1 } }
}
\ExplSyntaxOff
\newcommand\whatever[1]{%
\switchcase{#1}%
{
{ul}{\let\position\AtPageUpperLeft}
{ll}{\let\position\AtPageLowerLeft}
{pc}{\let\position\AtPageCenter}
}%
}
% Sentinel
\newcommand*\AtPageUpperLeft{AtPageUpperLeft}
\newcommand*\AtPageLowerLeft{AtPageLowerLeft}
\newcommand*\AtPageCenter {AtPageCenter}
\begin{document}
\whatever{ul}\position
\whatever{ll}\position
\whatever{pc}\position
\whatever{rubbish}\position % error!
\end{document}
对于宏,您可以使用\tl_case:nn
:
如果你想以与 catcode 无关的方式比较字符串,请使用\str_case:nn
对于整数,有\int_case:nn
对于尺寸,有\dim_case:nn
答案2
这是一个相当通用的 switch case 宏,基于expl3
。语法是
\switchcondition[<type>]{<input>}[<other>]{<cases>}
其中是、或(默认)中的一个,是<type>
针对案例进行测试的参数,是如果没有匹配的案例要做什么,是形式为string
token
integer
dimen
string
<input>
<other>
<cases>
{<case-1>}{<code-1>}
{<case-2>}{<code-2>}
[...]
{<case-n>}{<code-n>}
宏本身是完全可扩展的,但当然,只有当<other>
并且<code-k>
在每种情况下都完全可扩展时,才能利用此功能。
这是一个例子。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\switchcondition}{O{string}mmO{}}
{
\use:c { lyl_#1_switch:nnn } { #2 } { #3 } { #4 }
}
\cs_new:Nn \lyl_string_switch:nnn
{
\str_case:nnF { #1 } { #2 } { #3 }
}
\cs_new:Nn \lyl_token_switch:nnn
{
\tl_case:nnF { #1 } { #2 } { #3 }
}
\cs_new:Nn \lyl_integer_switch:nnn
{
\int_case:nnF { #1 } { #2 } { #3 }
}
\cs_new:Nn \lyl_dimen_switch:nnn
{
\dim_case:nnF { #1 } { #2 } { #3 }
}
\ExplSyntaxOff
\newcommand{\placement}[1]{%
\switchcondition{#1}{
{ul}{\let\position\AtPageUpperLeft}
{ll}{\let\position\AtPageLowerLeft}
{ur}{\let\position\AtPageUpperRight}
{lr}{\let\position\AtPageLowerRight}
}[\let\position\ERROR]%
}
% whatever these should do
\providecommand{\AtPageUpperLeft}{APUL}
\providecommand{\AtPageLowerLeft}{APLL}
\providecommand{\AtPageUpperRight}{APUR}
\providecommand{\AtPageLowerRight}{APLR}
\providecommand{\ERROR}{ERROR}
\newcommand{\foo}[1]{%
\switchcondition[integer]{#1}{
{1}{One}
{20}{Twenty}
{42}{The answer!}
}[Uninteresting number]%
}
\begin{document}
\placement{ul}\texttt{\meaning\position}
\placement{ll}\texttt{\meaning\position}
\placement{ur}\texttt{\meaning\position}
\placement{lr}\texttt{\meaning\position}
\placement{xy}\texttt{\meaning\position}
\foo{1}
\foo{6*7}
\foo{3456}
\end{document}
答案3
你也可以让 TeX 的 csname 哈希表为你进行查找,因此
\def\positionul{\let\position\AtPageUpperLeft}
\def\positionll{\let\position\AtPageLowerLeft}
\def\positionpc{\let\position\AtPageCenter}
然后在你没有显示的宏中,想要使用#1
,ul
或者ll
只是pc
使用
\csname position#1\endcsname
并且它将执行\positionll
如果#1
ll