我最近实现了一些命令/宏,我正在考虑减少命令/宏的参数数量。基本上,到目前为止,我已经使用 latex3 创建了一些宏xparse
。\cs_new:N
以下是一个例子:
\documentclass[a4paper]{article}
\ExplSyntaxOn
\NewDocumentCommand \foo {m}
{
\str_new:N \l_my_word
\str_set:Nn \l_my_word {#1}
\twice{\l_my_word}
}
\cs_new:Npn \twice #1
{
\str_use:N #1~\str_use:N #1
}
\ExplSyntaxOff
\begin{document}
\foo{Hello}
\end{document}
如果我理解正确的话,这里的“l”\l_my_word
只是一个命名约定。我也可以twice
按以下方式编写命令:
\cs_new:Npn \twice
{
\str_use:N \l_my_word~\str_use:N \l_my_word
}
\l_my_word
如果我知道我将在命令中使用变量,\twice
我是否必须使用该命令的第一个版本还是第二个版本?
谢谢你!
答案1
您提出问题的方式好像第二种形式违背了惯例,但事实并非如此,l_
前缀是当前组(而不是当前宏定义)本地名称的惯例,因此您在使用本地命令set
定义它时建议的两种形式都是这种情况。
所以两种形式都可以,取决于您是否想\twice
在其他情况下使用。
答案2
您的代码存在一些缺陷。
最主要的是\str_new:N
不应该放在 的定义中\foo
,而应该放在 的定义之外。对于您的代码,调用\foo
两次会导致错误。其次,所有变量的名称都应以变量类型结尾。此外,\twice
应该是一个expl3
函数。
这是一个可能的实现。
\documentclass[a4paper]{article}
\ExplSyntaxOn
\NewDocumentCommand \foo {m}
{
\str_set:Nn \l_lucarmand_word_str {#1}
\lucarmand_twice_str:N \l_lucarmand_word_str
}
\str_new:N \l_lucarmand_word_str
\cs_new:Npn \lucarmand_twice_str:N #1
{
\str_use:N #1~\str_use:N #1
}
\ExplSyntaxOff
\begin{document}
\foo{Hello}
\end{document}
但是,无需设置字符串变量就可以完成相同的任务,甚至可以完全扩展。
\documentclass[a4paper]{article}
\ExplSyntaxOn
\NewExpandableDocumentCommand \foo {m}
{
\lucarmand_twice:e { \tl_to_str:n { #1 } }
}
\cs_new:Nn \lucarmand_twice:n
{
#1~#1
}
\cs_generate_variant:Nn \lucarmand_twice:n { e }
\ExplSyntaxOff
\begin{document}
\foo{Hello}
\edef\test{\foo{Hello}}
\texttt{\meaning\test}
\end{document}