贪婪 \bool_if:n(TF) 是什么意思?

贪婪 \bool_if:n(TF) 是什么意思?

在最新的 CTAN 更新中,\bool_if:n(TF) 已贪婪的:...因此,任何仍然假设 \bool_if:n(TF) 进行惰性求值的代码都需要进行调整。

\bool_if:n(TF) 贪婪是什么意思?在这种情况下,惰性求值是什么意思?

我是否可以认为这\bool_if:NT \l__variable_bool不会受到影响?

答案1

布尔表达式的“贪婪”评估意味着每个子表达式都会被评估,并且只有在此之后完整的布尔表达式才会返回其值。

当仅评估决定表达式真假所必需的部分时,评估就是“懒惰的”。

在该expl3语言中,可以使用逻辑运算符“and” &&、“or”||或“not”!以及谓词和括号。

自 的上次更新以来expl3,出于实现原因,用作 的第一个参数的此类布尔表达式\bool_if:nTF需要进行贪婪求值。具体而言,每个子表达式都需要返回一个布尔值。

但是,expl3还通过特殊功能提供了惰性求值。

一个很重要的例子就是unicode-math更新后出现的那个问题,请参见TL 2017 更新后,unicode-math 编译失败

当前代码(待修复)unicode-math

\bool_if:nTF { \tl_if_single_p:n {##1} && \token_if_cs_p:N ##1 }
  { \seq_put_right:Nn \l_@@_cmd_range_seq {##1} }
  { \seq_put_right:Nn \l_@@_char_range_seq {##1} }

如果参数是单个标记,则第一个子表达式返回 true;对于惰性求值,如果返回 false,则无需检查第二部分即可得出条件为 false 的结论。对于贪婪求值,当第一部分返回 false 时,也会检查第二部分。

函数的目的是区分range选项中关键字的值是否\setmainfont由单个标记(即控制序列)组成。发生的事情是range=`\+没有通过测试\tl_if_single_p:n,因此没有尝试第二个条件;但是,在贪婪评估的情况下,仍然执行了第二个测试,导致错误,因为`\+不是有效的输入\token_if_cs_p:N

修复方法是使用惰性求值:

\bool_lazy_and:nnTF { \tl_if_single_p:n {##1} } { \token_if_cs_p:N ##1 }
  { \seq_put_right:Nn \l_@@_cmd_range_seq {##1} }
  { \seq_put_right:Nn \l_@@_char_range_seq {##1} }

其作用与之前相同。

“惰性”函数的lazy名称中包含:

\bool_lazy_all:nTF
\bool_lazy_any:nTF
\bool_lazy_and:nnTF
\bool_lazy_or:nnTF

前两个需要将任意数量的条件表达式作为第一个参数,每个条件表达式都用括号括起来,因此

\bool_lazy_all:nTF { {<cond-1>} {<cond-2>} ... { <cond-n> } }
 { <true code> }
 { <false code> }

如果全部条件返回 true,但一旦一个条件返回 false,就会停止评估;类似地

\bool_lazy_any:nTF { {<cond-1>} {<cond-2>} ... { <cond-n> } }
 { <true code> }
 { <false code> }

如果任何条件返回 true ,并且一旦返回 true 就会停止。

另外两个接收两个布尔表达式作为其第一个参数,并且是针对最常见情况的精简版本。

显然,这一变化不会影响\bool_if:NTF,因为这只会检查一个条件。然而,还有另一个与条件相关的变化:类似于

\bool_if:NTF \foo { <true> } { <false> }

当不是条件时,会跟随错误分支\foo。这种情况不会再发生(这是中断的原因mhchem)。


曾经有人想过,可以执行惰性求值,但结果却发现这很困难,难以管理,因此只针对“and”和“or”等简单情况引入了惰性求值函数。这发生在编写\bool_if:nTF代码之后。unicode-math

相关内容