这是 latex3 的一个通用且有文档记录的功能,但我仍将提供 MWE 来说明问题,见下文。
假设我有一个使用 l3keys 键值接口的函数,并且我希望它在用户不提供密钥时具有合理的默认值。l3keys 提供了default
和initial
选项,其中default
用于在提供密钥但没有值时使用,并initial
用于初始化密钥。但是,此初始化只发生一次,即在定义密钥时。
\documentclass{standalone}
\begin{document}
\ExplSyntaxOn
\keys_define:nn { mykeys } {
myvalue .int_set:N = \l_myvalue_int,
myvalue .initial:n = 0
}
\cs_new:Nn \show_zero_or_myvalue:n {
\keys_set:nn { mykeys } { #1 }
\int_use:N \l_myvalue_int
}
show_zero_or_myvalue:n {}
show_zero_or_myvalue:n { myvalue=5 }
show_zero_or_myvalue:n {}
\ExplSyntaxOff
\end{document}
作为用户,由于函数定义隐藏在某个包中,我期望这会导致输出050
。当然,一旦你读了 l3keys 文档,你就会知道它实际上会打印055
,因为在第三次调用中没有设置密钥myvalue
,所以它保留了之前的值。
然而,有些情况下这是不可取的。想象一下你用 TikZ 画了一幅画,代码
\tikz[color=black]{
% define some nodes
\draw[color=red] (a) -- (b);
\draw (b) -- (c);
}
导致出现两条红线。
显然,我可以手动重置后端的密钥,但由于我正在处理在多个地方读取的大量密钥,所以我目前的解决方法是在每一个致电\keys_set:nn { mykeys } { #1 }
,我发布了一份手册\keys_set:nn { mykeys } { ... }
,其中...
有一长串的按键列表。
有没有更好的方法来做到这一点,要么内置到 l3keys 中,要么通过挂接到set_keys
机制中?
不久前有人问过这个问题,但没有一个有明确的答案。由于 latex3 仍在开发中,我认为再次提问是合理的。
相关:如果没有内置方式,提出纳入此功能的标准机制是什么?显然,我不是唯一一个希望看到这样的事情的人。
答案1
针对此问题有两种策略。
其中一个是 Ti 也采用的钾Z,即分组。
\documentclass{article}
\begin{document}
\ExplSyntaxOn
\keys_define:nn { mykeys } {
myvalue .int_set:N = \l_myvalue_int,
myvalue .initial:n = 0
}
\cs_new_protected:Nn \show_zero_or_myvalue:n {
\group_begin:
\keys_set:nn { mykeys } { #1 }
\int_use:N \l_myvalue_int
\group_end:
}
\show_zero_or_myvalue:n {}
\show_zero_or_myvalue:n { myvalue=5 }
\show_zero_or_myvalue:n {}
\ExplSyntaxOff
\end{document}
由于按键的设置是在本地完成的,因此组结束后将恢复初始值。
第二种策略:保留一份需要重置的密钥列表。
\documentclass{article}
\begin{document}
\ExplSyntaxOn
\keys_define:nn { mykeys } {
myvalue .int_set:N = \l_myvalue_int,
}
\cs_new_protected:Nn \show_zero_or_myvalue:n {
\keys_set:nn { mykeys } { myvalue=0,#1 }
\int_use:N \l_myvalue_int
}
\show_zero_or_myvalue:n {}
\show_zero_or_myvalue:n { myvalue=5 }
\show_zero_or_myvalue:n {}
\ExplSyntaxOff
\end{document}
如果有多个键需要重置,你可以定义一个简写
\cs_new_protected:Nn \betta_reset: {
\keys_set:nn { mykeys } { myvalue=0 }
}
并在函数\betta_reset:
之前添加。\keys_set:nn
\show_zero_or_myvalue:n
答案2
另一种选择expl3
是@egreg 展示的可能性是将标准设置预编译为标记列表。这(原则上)与
第二种策略:保留一份需要重置的密钥列表。
但速度更快。
\documentclass{standalone}
\begin{document}
\ExplSyntaxOn
\tl_new:N \l_bettageorge_defaults_tl
\keys_define:nn { mykeys } {
myvalue .int_set:N = \l_myvalue_int,
myvalue .initial:n = 0
}
\keys_precompile:nnN { mykeys } { myvalue=0 } \l_bettageorge_defaults_tl
\cs_new_protected:Nn \show_zero_or_myvalue:n {
\l_bettageorge_defaults_tl
\keys_set:nn { mykeys } { #1 }
\int_use:N \l_myvalue_int
}
\show_zero_or_myvalue:n {}
\show_zero_or_myvalue:n { myvalue=5 }
\show_zero_or_myvalue:n {}
\ExplSyntaxOff
\end{document}