是否可以定义一个命令,重复以下命令 n 次?例如\Repeat
,
\Repeat[4] \command{...}
应该相当于
\command{...} \command{...} \command{...} \command{...}
答案1
这可以通过使用 以可扩展的形式实现\csname
。我个人会使用“预打包”版本expl3
:
\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new_eq:NN \Repeat \prg_replicate:nn
\ExplSyntaxOff
\begin{document}
\Repeat{4}{\command{...}}
\end{document}
对于那些手工编码的人来说,基本方法(最初由 David Kastrup 提出,由团队其他成员稍加修改)是
\catcode `\@ = 11\relax
\long\def\replicate#1{%
\romannumeral
\expandafter\replicate@first@aux\number#1%
\endcsname
}
\long\def\replicate@first@aux#1{%
\csname replicate@first@#1\replicate@aux
}
\chardef\rm@end=0 %
\long\expandafter\def\csname replicate@first@-\endcsname
#1{\rm@end\NegativeReplication}
\long\expandafter\def\csname replicate@first@0\endcsname
#1{\rm@end}
\long\expandafter\def\csname replicate@first@1\endcsname
#1{\rm@end #1}
\long\expandafter\def\csname replicate@first@2\endcsname
#1{\rm@end #1#1}
\long\expandafter\def\csname replicate@first@3\endcsname
#1{\rm@end #1#1#1}
\long\expandafter\def\csname replicate@first@4\endcsname
#1{\rm@end #1#1#1#1}
\long\expandafter\def\csname replicate@first@5\endcsname
#1{\rm@end #1#1#1#1#1}
\long\expandafter\def\csname replicate@first@6\endcsname
#1{\rm@end #1#1#1#1#1#1}
\long\expandafter\def\csname replicate@first@7\endcsname
#1{\rm@end #1#1#1#1#1#1#1}
\long\expandafter\def\csname replicate@first@8\endcsname
#1{\rm@end #1#1#1#1#1#1#1#1}
\long\expandafter\def\csname replicate@first@9\endcsname
#1{\rm@end #1#1#1#1#1#1#1#1#1}
\def\replicate@aux#1{%
\csname replicate@#1\replicate@aux
}
\long\expandafter\def\csname replicate@\endcsname#1{\endcsname}
\long\expandafter\def\csname replicate@0\endcsname
#1{\endcsname{#1#1#1#1#1#1#1#1#1#1}}
\long\expandafter\def\csname replicate@1\endcsname
#1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1}
\long\expandafter\def\csname replicate@2\endcsname
#1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1}
\long\expandafter\def\csname replicate@3\endcsname
#1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1}
\long\expandafter\def\csname replicate@4\endcsname
#1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1}
\long\expandafter\def\csname replicate@5\endcsname
#1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1}
\long\expandafter\def\csname replicate@6\endcsname
#1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1}
\long\expandafter\def\csname replicate@7\endcsname
#1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1}
\long\expandafter\def\csname replicate@8\endcsname
#1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1#1}
\long\expandafter\def\csname replicate@9\endcsname
#1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1#1#1}
\catcode `\@ = 12\relax
\edef\test{\replicate{20}{abc}}
\show\test
\bye
在expl3
版本中,\number#1
被 (有效) 替换为\number\numexpr#1\relax
,这允许将 '数字' 用于计算。如果您尝试使用负数,则故意未定义的控制序列会在扩展过程中引发错误,而不是稍后出现一些奇怪的错误。
第二种可扩展的方法是使用\romannumeral
,例如
\catcode `\@ = 11\relax
\def\replicate#1{%
\expandafter\replicate@aux\romannumeral\number #1000Q{}
}
\def\replicate@aux#1{\csname replicate@aux@#1\endcsname}
\long\def\replicate@aux@m#1Q#2#3{\replicate@aux#1Q{#2#3}{#3}}
\long\def\replicate@aux@Q#1#2{#1}
\edef\test{\replicate{5}{a}}
\show\test
\bye
这比方法更清晰\csname
,但实际上又是一个循环,因此慢的进行大量重复。
答案2
您可以使用\foreach
PGF/TikZ 中的 -command。
\documentclass{minimal}
\usepackage{pgffor}
\newcommand{\cmd}{-x-}
% to provide your syntax
\newcommand{\Repeat}[2]{% \repeat already defined
\foreach \n in {1,...,#1}{#2}
}
\begin{document}
\foreach \n in {1,...,4}{\cmd}
\Repeat{6}{\cmd}
\end{document}
更多信息请参阅手册.pdf,第 56 节,第 504 页及下文。
还有一个TeX-Way例如这一页(在德国 …)
答案3
multido
有一个简单的复制界面:
\documentclass{article}
\usepackage{multido}
\newcommand{\cmd}{-x-}
\newcommand{\Repeat}{\multido{\i=1+1}}
\begin{document}
\Repeat{6}{\cmd}
\end{document}
答案4
简单明了(双关语):
\def\foo{keke}
\def\bar#1#2{\count0=#1 \loop \ifnum\count0>0 \advance\count0 by -1 #2\repeat}
\bar3\foo % results in kekekekekeke
\bye
标记列表寄存器扩展得更快,因此如果它适合您,您还可以执行以下操作:
\newtoks\foo \foo={keke}
\def\bar#1#2{\count0=#1 \loop \ifnum\count0>0 \advance\count0 by -1 \the#2\repeat}
\bar3\foo % results in kekekekekeke
\bye
使用 e-tex 附加功能以可扩展的方式重复(来自http://www.tug.org/TUGboat/tb29-2/tb92jackowski.pdf):
\def\foo{keke}
\def\gobbleone#1{}
\long\def\replicate#1#2{%
\ifnum\numexpr#1>0
#2\expandafter\replicate\expandafter
{\number\numexpr#1-1\expandafter}%
\else
\expandafter\gobbleone
\fi{#2}}
\replicate3\foo % results in kekekekekeke
\bye