如果我想用 LaTeX3 语法定义一个宏,并对其参数进行一级扩展(:o
),我认为这种方式不够\cs_new
。相反,我必须将\cs_new
其转换为:n
,然后创建一个:o
变体。
这是错误还是功能?如果是后者,则没有很好的文档记录。
\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\cs_new_protected:Nn \__a_one:o
{
\tl_clear_new:N \__a_tmp_tl
\tl_set:Nn \__a_tmp_tl {#1}
\tl_show:N \__a_tmp_tl % returns \__a_abc_tl - Why is there no expansion?
}
\cs_new_protected:Nn \__a_two:n
{
\tl_clear_new:N \__a_tmp_tl
\tl_set:Nn \__a_tmp_tl {#1}
\tl_show:N \__a_tmp_tl % correctly returns abc with the :o variant
}
\cs_generate_variant:Nn \__a_two:n {o}
\tl_new:N \__a_abc_tl
\tl_set:Nn \__a_abc_tl {abc}
\__a_one:o { \__a_abc_tl }
\__a_two:o { \__a_abc_tl }
\end{document}
答案1
让我引用第 3.1 节的最后一段interface3.pdf
:
最后,第 3.2 和 3.3 小节中的函数主要用于定义基函数。基函数只能具有以下参数说明符:
N
和n
沒有執行。
T
和F
功能上等同于n
(实际上鼓励您使用\prg_new_conditional:
第 1 节中描述的函数系列)。
p
和 w这些都是特殊情况。下面的函数
\cs_new:
(和朋友)不会阻止您在函数名称中使用其他参数说明符,但它们不会为您处理扩展。您应该定义基函数,然后使用它\cs_generate_variant:Nn
来生成自定义变体,如第 2 节所述。
第 2 部分内容如下:
\cs_generate_variant:Nn
⟨父控制序列⟩{
⟨变体参数说明符⟩}
此函数用于定义 ⟨父控制序列⟩ 适用于 LaTeX3 代码级宏。⟨父控制序列⟩ 首先被分离成 ⟨基名称⟩ 和 ⟨原始参数说明符⟩. ⟨ 的逗号分隔列表变体参数说明符然后使用 ⟩ 来定义 ⟨ 的变体原始参数说明符⟩ 其中这些尚未定义。对于每个 ⟨变体⟩ 给定一个函数,它将展开其参数并将其传递给 ⟨父控制序列⟩.
这并不涉及魔法。当你说 时\cs_new_protected:Nn
,你正在使用\def
或\gdef
伪装。虽然它可以原则上可以检查给定的签名并使用合适的扩展机制定义函数,毫无疑问最好一步一步来:
\cs_new_protected:Nn \__a_one:n
{
...
}
\cs_generate_variant:Nn \__a_one:n { o }
因为\__a_one:n
无论如何都要定义该函数。因此没有必要为此设置复杂的机制。
更具体地说,在该代码之后,的含义\__a_one:o
是
\exp_args:No \__a_one:n
\cs_new_protected:Nn \__a_one:o
对于假设处理所需的扩展来说,没有其他实际的方法可以从\__a_one:n
根本上进行定义,然后应用\cs_generate_variant:Nn
。
我的经验表明好的:您始终知道有哪些可用功能,因为您定义了所有功能。