Paul Gaborit 的回答如何检测是否通过 \tikzset 提供选项用途
\newbool
定义一个新的布尔值\booltrue
设置布尔值,以及\ifbool
执行条件运算
全部来自包裹etoolbox
嗯,我一直在使用
\newtoggle
定义一个新的切换按钮\toggletrue
设置切换按钮,然后\iftoggle
执行条件运算
也来自同一个包。
这两者之间有什么区别吗?哪一个更可取?
代码:
\documentclass{article}
\usepackage{etoolbox}
\newtoggle{ToggleCondition}
\newbool{BooleanCondition}
\newcommand*{\CheckBoolean}{\ifbool{BooleanCondition}{true}{false}}
\newcommand*{\CheckToggle}{\iftoggle{ToggleCondition}{true}{false}}
\begin{document}
\toggletrue{ToggleCondition}
ToggleCondition is \CheckToggle.
\togglefalse{ToggleCondition}
ToggleCondition is \CheckToggle.
\medskip
\booltrue{BooleanCondition}
BooleanCondition is now \CheckBoolean.
\boolfalse{BooleanCondition}
BooleanCondition is now \CheckBoolean.
\end{document}
答案1
\newbool{mybool}
\newif
几乎与但它会检查是否\ifmybool
已经定义,而 LaTeX 不会:
\newrobustcmd*{\newbool}[1]{%
\expandafter\@ifdefinable\csname if#1\endcsname{%
\expandafter\newif\csname if#1\endcsname}}
\providebool
如果条件已经定义,则不执行任何操作。
类似地,\ifbool
是通常构造的包装器
\if...
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
初步检查条件是否已定义。因此它也可以用于原始条件:
\ifbool{hmode}{<something for horizontal mode>}{<something else>}
相反\newtoggle{mytoggle}
定义为
\newrobustcmd*{\newtoggle}[1]{%
\ifcsdef{etb@tgl@#1}
{\etb@error{Toggle '#1' already defined}\@eha}
{\cslet{etb@tgl@#1}\@secondoftwo}}
因此它会检查切换是否已定义,如果没有,则将其设置为“false”。构造的宏\etb@tgl@mytoggle
要么是\@firstoftwo
(对应于“true”),要么是\@secondoftwo
(对应于“false”)。当有人说
\iftoggle{mytoggle}{<true>}{<false>}
etoolbox
只需检查切换是否已定义,如果已定义,则仅放入\etb@tgl@mytoggle
输入流,从而做“正确的事情”,因为它会根据是否是<true>
或来选择或。<false>
\@firstoftwo
\@secondoftwo
注意\toggletrue
定义为
\newrobustcmd*{\toggletrue}[1]{%
\ifcsdef{etb@tgl@#1}
{\cslet{etb@tgl@#1}\etb@toggletrue}
{\etb@noglobal\etb@err@notoggle{#1}}}
因此可以在其前面加上\global
:确实是可扩展的,因此如果没有定义\ifcsdef
切换,则之后我们将继续使用foo
\global\toggletrue{foo}
\global\etb@noglobal\etb@err@notoggle{#1}}
变成
\global\let\relax\relax\etb@err@notoggle{#1}
\global
通过执行无害的操作\let
(几乎无害,因为它会影响堆栈内存,但由于无论如何都会引发错误,因此用户将更正它),可以有效地删除。如果\foo
定义了切换,我们仍然
\global\cslet{etb@tgl@foo}\etb@toggletrue
所以,再说一遍,
\global\expandafter\let\csname etb@tgl@foo\endcsname\etb@toggletrue
其中\etb@toggletrue
与 相同\@firstoftwo
。当然, 也同样如此\togglefalse
。
哪一个更适合你?如果你也打算使用传统\if...
语法,那么\newbool
就需要。否则,这只是个人喜好问题。
布尔值和切换都可以在布尔表达式 ( ) 中使用\ifboolexpr
,因此这种用法也没有区别。请注意\global\booltrue
和\global\boolfalse
也是合法的。
答案2
答案在etoolbox
文档根据第3.5 布尔标志(第 12 页起):
3.5.1 TeX 标志
由于本节中的工具基于\newif
内部,因此它们可用于测试和更改先前用 定义的标志的状态\newif
。它们还与包的布尔测试兼容ifthen
,可以用作查询 TeX 基元(如 )的 LaTeX 接口\ifmmode
。该\newif
方法每个标志总共需要三个宏。
这意味着使用\newbool{cs}
类似于\newif\ifcs
创建 3 个宏:\ifcs
、\cstrue
和\csfalse
。
3.5.2 LaTeX 标志
与 3.5.1 节中的标志不同,本节中的工具每个标志仅需要一个宏。它们还使用单独的命名空间,以避免与常规宏发生名称冲突。
这为每个标志使用一个宏。对“命名空间”的引用意味着您可以使用
\newbool{mybool}
\newtoggle{mybool}
而不会遇到问题。
偏好?在我看来,这取决于用户。早在 80 年代,当内存可用性成为人们关注的问题时,也许人们\newtoggle
会更喜欢它……但我们生活在现在,没有这种限制。
一些技术细节来自etoolbox.sty
:
\newbool
相当于\newif
,除了确保条件可以通过以下方式定义\@ifdefinable
:\newrobustcmd*{\newbool}[1]{% \expandafter\@ifdefinable\csname if#1\endcsname{% \expandafter\newif\csname if#1\endcsname}}
\newtoggle{cs}
创建\etb@tgl@cs
:\newrobustcmd*{\newtoggle}[1]{% \ifcsdef{etb@tgl@#1} {\etb@error{Toggle '#1' already defined}\@eha} {\cslet{etb@tgl@#1}\@secondoftwo}}