重复命令 n 次?

重复命令 n 次?

是否可以定义一个命令,重复以下命令 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

您可以使用\foreachPGF/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

相关内容