如果需要在 TeX 将参数传递给宏之前对其进行预处理/扩展,则可以在 expl3 中执行两件事:
- 用于
\cs_generate_variant:Nn
生成宏的变体,其中参数经过预处理。 - 使用
\exp_args:N...
在下面的第一个例子中,
\mymodule_foo:o { \mymodule_bar: }
生成与相同的消息
\exp_args:No \mymodule_foo:n { \mymodule_bar: }
。
问题是:
除了
- 减少 .tex 输入文件大小的目标,
- LaTeX 运行期间的内存消耗(假设它没有出现在许多宏的定义文本中)对于该
\exp_args:N...
变体来说应该更低,因为不需要存储额外的宏, - 代码的可读性
- LaTeX 运行的持续时间/运行时间
那么,是否有其他标准/条件来选择其中一种方法?
如果是:哪些?
这两种方法哪一种更快?
\ExplSyntaxOn
\msg_new:nnnn {mymodule} {generic} {#1} {}
\cs_new:Nn \mymodule_foo:n
{
\msg_term:nnn {mymodule} {generic} {
This~is~the~argument~of~\mymodule_foo: #1
}
}
\cs_generate_variant:Nn \mymodule_foo:n { o }
\cs_new:Nn \mymodule_bar:
{
Toplevel~expansion~of~\mymodule_bar:
}
\mymodule_foo:o {\mymodule_bar:}
\exp_args:No \mymodule_foo:n {\mymodule_bar:}
\stop
我提到可读性是因为\exp_args:N...
当处理需要预处理的多个参数时,代码很快就会让没有经验的人感到困惑:
\ExplSyntaxOn
\msg_new:nnnn {mymodule} {generic} {#1} {}
\cs_new:Nn \mymodule_foo:nnn
{
\msg_term:nnn {mymodule} {generic} { 1st~argument~of~\mymodule_foo: #1 }
\msg_term:nnn {mymodule} {generic} { 2nd~argument~of~\mymodule_foo: #2 }
\msg_term:nnn {mymodule} {generic} { 3rd~argument~of~\mymodule_foo: #3 }
}
\cs_generate_variant:Nn \mymodule_foo:nnn { ooo }
\cs_new:Nn \mymodule_bar: { Toplevel~expansion~of~\mymodule_bar: }
\cs_new:Nn \mymodule_bas: { Toplevel~expansion~of~\mymodule_bas: }
\cs_new:Nn \mymodule_bat: { Toplevel~expansion~of~\mymodule_bat: }
% This is readable:
\mymodule_foo:ooo {\mymodule_bar:}{\mymodule_bas:}{\mymodule_bat:}
\msg_term:nnn
{mymodule} {generic}
{ ------------------------------------------------------------------- }
% This is sort of readable:
\exp_args:Nooo \mymodule_foo:nnn {\mymodule_bar:}{\mymodule_bas:}{\mymodule_bat:}
\msg_term:nnn
{mymodule} {generic}
{ ------------------------------------------------------------------- }
% This might occur confusing:
\exp_args:Nno \use:n {
\exp_args:Nno \use:n {
\exp_args:No \mymodule_foo:nnn {\mymodule_bar:}
} {\mymodule_bas:}
} {\mymodule_bat:}
\stop
答案1
总体而言,团队的建议侧重于可读性:这里的性能差异很小。我们提倡的方法是强烈支持\cs_generate_variant:Nn
,而“直接”使用\exp_args:N...
保留给
- 变体仅使用一次的地方
- 无法使用变体的情况:通常是动态生成 csname