对于 pstricks 项目,我有一个包含 9 个参数的宏,每个参数都以相同的方式由宏处理。显然,我更愿意使用循环,而不是为每个参数编写 9 次相同的代码。为此,我需要通过索引访问参数。例如
\def\foo#1{...}
\def\bar#1#2#3#4#5#6#7#8#9{
\foreach \i in {1,...,9}{
\if ... % parameter #\i has some property
\bar{#\i}
\fi
}
}
我怎样才能做到这一点?(上面的代码显然无法编译。)
我在网上搜索了好几天,并没有发现任何令我惊讶的东西。
在此先感谢您的帮助。
答案1
参数替换仅在 TeX 扩展宏时发生,因此您无法像尝试的那样稍后通过数字访问它们。如果您想任意访问参数,您必须定义临时宏,以便您可以通过名称访问这些宏。例如:
\def\bar#1#2#3#4#5#6#7#8#9{%
% save the parameters:
\def\bartmpi{#1}%
\def\bartmpii{#2}%
\def\bartmpiii{#3}%
\def\bartmpiv{#4}%
\def\bartmpv{#5}%
\def\bartmpvi{#6}%
\def\bartmpvii{#7}%
\def\bartmpviii{#8}%
\def\bartmpix{#9}%
%
% some complex computation:
\def\barnum{5}%
% access the macro with \csname ..\endcsname
\csname bartmp\romannumeral\barnum\endcsname
}
\bar{1}{9}{2}{8}{3}{7}{4}{6}{5}
如果您只想循环遍历 1 到 9,那么您只需映射参数列表并执行一些操作,例如使用\tl_map_inline:nn
(在 内部\tl_map_inline:nn
,当前项目是##1
):
\ExplSyntaxOn
\cs_new_eq:NN \TlMapInline \tl_map_inline:nn
\ExplSyntaxOff
\def\bar#1#2#3#4#5#6#7#8#9{%
\TlMapInline{{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}}
{%
\ifnum##1>5
(##1)%
\else
[##1]%
\fi
}%
}
\bar{1}{9}{2}{8}{3}{7}{4}{6}{5}
答案2
我建议不要使用 9 个单独的参数,而是使用一个带有内部分隔符的参数(这里是逗号,
,可以用 进行更改\setsepchar
,请参阅listofitems
文档)
\documentclass{article}
\usepackage{listofitems}
\begin{document}
\newcommand\foo[2]{%
\ifnum #1=5 % parameter #\i has some property
\textbf{#2}/%
\else
#2/%
\fi
}
\newcommand\barr[1]{%
\readlist*\myargs{#1}%
\foreachitem\z\in\myargs[]{\foo{\zcnt}{\z}}
}
\barr{a,bb,d, hi mom, \today,zz, d,,!!}
\end{document}
另一种方法是将这 9 个参数传递给递归例程。这样,如果您的文档已经使用了它,则调用语法无需更改。
\documentclass{article}
\def\foo#1{#1/}
\def\barr#1#2#3#4#5#6#7#8#9{%
\iftrue\barrhelp{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}\fi}
\def\barrhelp#1#2\fi{\fi\foo{#1}\ifx\relax#2\relax\else\barrhelp#2\fi}
\begin{document}
\barr{A}{B}{C}{DD}{E}{Ff}{G}{HHH}{i}
\end{document}
答案3
这里的答案使用了各种工具。我展示了另一种工具,\foreach
来自 OpTeX。此外:由于参数在\bar
宏中被读入空格分隔符,因此您可以使用\bar
任意数量的参数。
\def\bar#1 {%
\foreach #1 \do
{%
\ifnum##1>5
(##1)%
\else
[##1]%
\fi
}%
}
\bar{1}{9}{2}{8}{3}{7}{4}{6}{5}{12}{1}{13}
答案4
(!!!这个答案是“学术性的”=不适用于实际使用场景!!!
\bar
在 LaTeX 2ε 中已经定义,因此下面使用\FOO
和代替。)\BAR
如果您确实想要这样做,则可以\foreach
使用临时宏 ( \MYtempadefiner
) 来在每次迭代中定义另一个临时宏 ( \MYtempa
)。请记住,#
在 中定义(临时)宏时,哈希 ( ) 需要加倍\foreach
。在宏定义中编写宏定义时,它们也需要加倍。
\documentclass[a4paper]{article}
\usepackage{tikz}
\newcommand\FOO[1]{\par \noindent Argument is: #1}
\newcommand\BAR[9]{%
\def\MYtempadefiner##1{%
\def\MYtempa####1####2####3####4####5####6####7####8####9{%
%\if parameter ##1 has some property%
\FOO{##1}%
%\fi
}%
}%
\foreach \i in {1,...,9}{%
%if (expansion of) \i has some property%
\expandafter\MYtempadefiner\expandafter{\expandafter####\i}%
\MYtempa{#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8}{#9}%
%\fi
}%
}%
\begin{document}
\BAR{1}{2}{3}{4}{5}{6}{7}{8}{9}%
\end{document}