向命令或宏传递参数的最佳实践

向命令或宏传递参数的最佳实践

我最近实现了一些命令/宏,我正在考虑减少命令/宏的参数数量。基本上,到目前为止,我已经使用 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}

在此处输入图片描述

相关内容