etoolbox 包中的 \newbool 和 \newtoggle 之间的区别

etoolbox 包中的 \newbool 和 \newtoggle 之间的区别

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}}
    

相关内容