如何\newcommand
通过迭代变量访问声明的第 i 个参数?
假设我想要如下命令\foo
:
\newcommand{\barr}[1]{argument 1 is: #1}
\newcommand{\foo}[6]{
\foreach \i in {1,...,6}
\barr{#\i}; %this does not work. \barr{#1}, \barr{#6} do work
}
编辑:根据要求,提供一些背景信息。我想要一个命令,比如\foo{1}{2}{5}{0}{1}{2}
在第一部分画 1 个球,在第二部分画 2 个球,在第三部分画 5 个球,等等。一切正常,我唯一缺少的是以方便的方式访问第 i 个参数。
答案1
\whiledo
对于\foreach
OP 来说,这可能被接受,也可能不被接受。
\documentclass{article}
\usepackage{stringstrings}
\newcounter{index}
\newcommand{\barr}[2]{argument #1 is: #2\par}
\newcommand\foo[1]{%
\getargs{#1}%
\setcounter{index}{0}%
\whiledo{\theindex < \narg}{%
\stepcounter{index}%
\barr{\theindex}{\csname arg\romannumeral\theindex\endcsname}%
}%
}
\begin{document}
\foo{A B C D EE F GGG H I JJJ K FinalArgument}
\end{document}
答案2
您不能以那种方式指定宏;#1
,#2
等等必须在定义时确实存在,因为它们代表占位符。
我不明白为什么要限制为六个:对于五个或八个,你可能需要相同的数量。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\foo}{ O{,} m}
{
\mort_add_bar:nn { #1 } { #2 }
}
\seq_new:N \l_mort_input_seq
\seq_new:N \l_mort_output_seq
\cs_new_protected:Npn \mort_add_bar:nn #1 #2
{
% split the input at the comma (or what's in the optional argument)
\seq_set_split:Nnn \l_mort_input_seq { #1 } { #2 }
% clear the output section
\seq_clear:N \l_mort_output_seq
% put each item inside \bar{...}
\seq_map_inline:Nn \l_mort_input_seq
{
\seq_put_right:Nn \l_mort_output_seq { \bar{ ##1 } }
}
% output the sequence, separated by semicolons
\seq_use:Nn \l_mort_output_seq { ; }
}
\ExplSyntaxOff
\begin{document}
$\foo{a,b,c}$
% just to show that you can change the
% delimiter and have as many items as you wish
$\foo[.]{a.b.c.e.f.g.h.i}$
\end{document}
为了绘制多个对象,这里有一个可能的解决方案:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\foo}{ O{,} m }
{
\mort_add_bar:nn { #1 } { #2 }
}
\seq_new:N \l_mort_input_seq
\cs_new_protected:Npn \mort_add_bar:nn #1 #2
{
\seq_set_split:Nnn \l_mort_input_seq { #1 } { #2 }
\seq_map_inline:Nn \l_mort_input_seq
{
\mort_draw_balls:n { ##1 }
}
}
\cs_new_protected:Npn \mort_draw_balls:n #1
{
/
\prg_replicate:nn { #1 } { \textbullet }
/
}
\ExplSyntaxOff
\begin{document}
\foo{1,2,5,0,1,2}
% just to show that you can change the
% delimiter and have as many items as you wish
\foo[-]{1-3-4}
\end{document}
答案3
egreg 和 Steven B. Segletes 的解决方案当然很棒。但是,如果参数数量固定,那么这似乎有点过头了。
另外,这个也可以:
\newcommand{\bar}[1]{argument 1 is: #1}
\newcommand{\foo}[6]{
\foreach \i/\j in {1/#1,2/#2,3/#3,4/#4,5/#5,6/#6}
\putinbin{\i}{\j};
}
答案4
我认为 TeX-core 无法以简单的方式实现这一点。最简单的方法可能是以下方法,但它既不美观也不高效,因为你必须输入正确的项数(否则 TeX-core 会抱怨参数无效)。
\newcommand{\bar}[1]{argument 1 is: #1}
\newcommand{\foo}[6]{
\foreach \i in {1,...,6}
\bar{\ifcase\i\or#1\or#2\or#3\or#4\or#5\or#6\fi};
}