在我的LaTeX
实验室里,我正在做一些奇怪的实验expl3
(几天前才开始使用它,所以l3
我完全是新手)
我正在尝试在另一个宏中生成命令序列,其名称基于外部宏的宏参数。
这LaTeX(2e)
很容易
\newcommand{\foo}[1]{%
\expandafter\newcommand\csname foo#1\endcsname{Hello World}
}
并\foo{bar}
定义\foobar
(当然,在这里没什么用)
我尝试将这种方式(用 替换)应用\expandafter
到\exp_after:wN
命令expl3
序列中并且\cs_new:Nn
它可以工作,但我想知道:
有没有更好、更干净的方法来获得它
expl3
,而不使用\csname
等等,而只是从签名或使用变体?
PS 我知道,这些expl3
命令实际上并不是用于排版的,输出Hello World
仅仅是一个例子。
\documentclass{article}
% Module named foo ;-)
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\foo}{m}{%
\exp_after:wN\cs_new:Nn \csname foo_#1:\endcsname {Hello\space World}
}
\NewDocumentCommand{\foocall}{}{%
\foo{start} % define \foo_start:
\foo_start:
}
\ExplSyntaxOff
\begin{document}
\foocall
\end{document}
关于扩展的一个不太相似的问题是使用 LaTeX3 泛化宏,所以我不认为我的问题重复了。
答案1
定义修改可能应该真正限制在编程(expl3)层,仅通过 xparse 定义顶层“latex2e”接口\NewDocumentCommand
,而且在 l3 中如果你定义命令首先采用正常\zzzz
参数那么\expandafter\...\csname
习语被预先打包为“定义c
变体”会更清晰,所以...
\documentclass{article}
% Module named foo ;-)
\usepackage{xparse}
\ExplSyntaxOn
\cs_new:Npn\foo:N#1{\show#1\cs_new:Npn#1{Hello ~ World}}
\cs_generate_variant:Nn\foo:N{c}
\NewDocumentCommand{\foocall}{}{%
\foo:c{foo_start:} % define \foo_start:
\foo_start:
}
\ExplSyntaxOff
\begin{document}
\foocall
\end{document}
答案2
接口已经存在,只需使用c
类型参数代替N
:
\documentclass{article}
% Module named foo ;-)
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\foo}{m}{%
\cs_new:cn {foo_#1:}{Hello ~ World}
}
\NewDocumentCommand{\foocall}{}{%
\foo{start} % define \foo_start:
\foo_start:
}
\ExplSyntaxOff
\begin{document}
\foocall
\end{document}
答案3
我知道你在文章标题中提到了 expl3。但是我们已经有 TeX 原始语言来做这样的事情 30 年了。
\def\sdef#1{\expandafter\def\csname#1\endcsname}
\def\foo#1{\sdef{foo#1}{Hello World}}
\def\foocall{\foo{start}\foostart}
\foocall
为什么要重新发明轮子?为什么要学习和使用一种新的更复杂的语言?