我正在尝试操作多个布尔变量,这些变量简单命名为,,,one
等等,并且因为我将它们与计数器一起使用,所以我定义了一些命令来接受数字输入并处理布尔值:two
three
\newif\ifp@one@
\newif\ifp@two@
\newif\ifp@three@
\def\p@settrue@#1{
\ifnum#1 =1 \p@one@true \else
\ifnum#1 =2 \p@two@true \else
\ifnum#1 =3 \p@three@true
\fi\fi\fi}
\def\p@setfalse@#1{<same as with true>}
\def\p@if@#1{
\ifnum#1 =1 \expandafter\ifp@one@ \else
\ifnum#1 =2 \expandafter\ifp@two@ \else
\ifnum#1 =3 \expandafter\ifp@three@
\fi\fi\fi}
前两个命令工作正常,所以如果我运行\p@settrue@1
,那么\ifp@one@
现在就是true
。
第三个函数的问题在于\p@if@
:我无法让它工作。我以为只需\expandafter
在每个函数前添加一个\ifp@<number>@
,但这个函数不起作用。
理想情况下,我希望使用它
\p@if@1
<do something>
\else
<do something else>
\fi
为什么这不起作用?
我意识到我可以定义
\def\p@if@#1#2#3{
\ifnum#1 =1 \ifp@one@#2\else#3\fi \else
\ifnum#1 =2 \ifp@two@#2\else#3\fi \else
\ifnum#1 =3 \ifp@three@#2\else#3\fi
\fi\fi\fi}
这是一个不错的选择,但我仍然好奇为什么上面的代码会失败。
答案1
建立从数字到文本表示的转换表:
\catcode`@=11
\def\p@translate#1{%
\ifcase#1\or one\or two\or three\fi
}
\def\p@settrue@#1{%
\csname p@\p@translate{#1}@true\endcsname
}
\def\p@setfalse@#1{%
\csname p@\p@translate{#1}@false\endcsname
}
\def\p@cond@#1{%
TT\fi
\csname ifp@\p@translate{#1}@\endcsname
}
\newif\ifp@one@
\newif\ifp@two@
\newif\ifp@three@
% Testing
\def\msg#{\immediate\write16}
\p@settrue@{1}
\if\p@cond@{1}\msg{1 = true}\else\msg{1 = false}\fi
\if\p@cond@{3}\msg{3 = true}\else\msg{3 = false}\fi
\bye
由于不可能有一个像跳过的文本中的条件一样正确运行的宏,因此TT\fi
使用了这个技巧,因此你调用
\if\p@cond@{1}%
<text to be executed if conditional 1 is true>%
\else
<text to be executed if conditional 1 is false>%
\fi
输出:
1 = true
3 = false
答案2
由于嵌套结构, 的定义\p@if@
未按预期工作\if
。需要更多 来\expandafter
清理结束\else
和\fi
标记。
以下示例使用\csname
构造来简化清理并更改语法。\iftrue
位于 之前\p@if@
。 后者是一个宏,TeX 不会将其识别为\if
命令的一部分。 当 TeX 跳过分支时,它不会检查宏。 构造也可以在构造\iftrue\p@if@
内部使用。\if
\catcode`\@=11
\newif\ifp@one@
\newif\ifp@two@
\newif\ifp@three@
\def\p@settrue@#1{
\ifcase#1\or
\p@one@true\or
\p@two@true\or
\p@three@true
\fi
}
\def\p@setfalse@#1{
\ifcase#1\or
\p@one@false\or
\p@two@false\or
\p@three@false
\fi
}
\def\p@if@#1{%
\fi
\csname if%
\ifcase#1false\or
\ifp@one@ true\else false\fi\or
\ifp@two@ true\else false\fi\or
\ifp@three@ true\else false\fi\else
false%
\fi
\endcsname
}
% Testing
\def\msg#{\immediate\write16}
\p@settrue@1
\iftrue\p@if@1\msg{1 = true}\else\msg{1 = false}\fi
\iftrue\p@if@3\msg{3 = true}\else\msg{3 = false}\fi
\csname @@end\endcsname\end
结果:
1 = true
3 = false