Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Is it possible to define a command, which repeats the following command n-times? Call it for example \Repeat, then

\Repeat[4] \command{...} 

should be equivalent to

\command{...} \command{...} \command{...} \command{...} 
share|improve this question
    
Note that \repeat is already defined by LaTeX as end-macro for \loop. –  Martin Scharrer Apr 19 '11 at 19:34

5 Answers 5

up vote 17 down vote accepted

This can be done in an expandable form using \csname. I would personally use the 'pre-packed' version in expl3:

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new_eq:NN \Repeat \prg_replicate:nn
\ExplSyntaxOff
\begin{document}
\Repeat{4}{\command{...}}
\end{document}

For those who would code by hand, the basic approach (thanks to David Kastrup) is

\catcode `\@ = 11\relax
\def\replicate#1{%
  \csname empty\expandafter \replicate@first@aux
    \romannumeral - `0\number#1\endcsname
  \endcsname
}
\def\replicate@first@aux#1{%
  \csname replicate@first@#1\replicate@aux
}
\expandafter\long\expandafter\def\csname replicate@first@-\endcsname
  #1{\endcsname\NegativeReplication}
\expandafter\long\expandafter\def\csname replicate@first@0\endcsname
  #1{\endcsname}
\expandafter\long\expandafter\def\csname replicate@first@1\endcsname
  #1{\endcsname #1}
\expandafter\long\expandafter\def\csname replicate@first@2\endcsname
  #1{\endcsname #1#1}
\expandafter\long\expandafter\def\csname replicate@first@3\endcsname
  #1{\endcsname #1#1#1}
\expandafter\long\expandafter\def\csname replicate@first@4\endcsname
  #1{\endcsname #1#1#1#1}
\expandafter\long\expandafter\def\csname replicate@first@5\endcsname
  #1{\endcsname #1#1#1#1#1}
\expandafter\long\expandafter\def\csname replicate@first@6\endcsname
  #1{\endcsname #1#1#1#1#1#1}
\expandafter\long\expandafter\def\csname replicate@first@7\endcsname
  #1{\endcsname #1#1#1#1#1#1#1}
\expandafter\long\expandafter\def\csname replicate@first@8\endcsname
  #1{\endcsname #1#1#1#1#1#1#1#1}
\expandafter\long\expandafter\def\csname replicate@first@9\endcsname
  #1{\endcsname #1#1#1#1#1#1#1#1#1}
\def\replicate@aux#1{%
  \csname replicate@#1\replicate@aux
}
\expandafter\long\expandafter\def\csname replicate@\endcsname#1{}
\expandafter\long\expandafter\def\csname replicate@0\endcsname
  #1{\endcsname{#1#1#1#1#1#1#1#1#1#1}}
\expandafter\long\expandafter\def\csname replicate@1\endcsname
  #1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1}
\expandafter\long\expandafter\def\csname replicate@2\endcsname
  #1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1}
\expandafter\long\expandafter\def\csname replicate@3\endcsname
  #1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1}
\expandafter\long\expandafter\def\csname replicate@4\endcsname
  #1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1}
\expandafter\long\expandafter\def\csname replicate@5\endcsname
  #1{\endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1}
\expandafter\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}
\expandafter\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}
\expandafter\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}
\expandafter\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

In the expl3 version, the \number#1 is (effectively) replaced by \number\numexpr#1\relax, which allows the 'number' used to be a calculation. If you try a negative number, the deliberately-undefined control sequence raises an error as part of the expansion, rather than having some odd error later.


A second approach which is expandable and does not require e-TeX is to use \romannumeral, for example

\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

This is clearer to code than the \csname approach, but is effectively a loop again and so gets slow for large numbers of repetitions.

share|improve this answer
    
Ah, I should have known that LaTeX3 is having something like this. I coded something by myself and just saw your post. –  Martin Scharrer Apr 19 '11 at 19:56
    
Note that while this seems like a overkill-approach, it should be (much?) more efficient than the simpler looping code proposed in other answers. –  Will Robertson Apr 20 '11 at 9:20
    
As @Will says, this approach scales well (I use it for testing purposes often with 100k repetitions). –  Joseph Wright Apr 20 '11 at 9:28
    
The important point to notice about the code is that it replicates for each power of ten. So as the number gets very big, rather than lots of single repetitions each 'level' requires only one pass. –  Joseph Wright Apr 20 '11 at 9:56
    
However, for huge number of repetitions, since all the repetitions are held in TeX's memory, we can overflow it. A solution in that case is \prg_replicate:nn {10000}{\prg_replicate:nn {10000}{...}}. Not needed often. –  Bruno Le Floch May 13 '11 at 8:41

multido has a simple interface for replication:

enter image description here

\documentclass{article}
\usepackage{multido}
\newcommand{\cmd}{-x-}
\newcommand{\Repeat}{\multido{\i=1+1}}
\begin{document}

\Repeat{6}{\cmd}
\end{document}
share|improve this answer

Plain and simple (pun intended):

\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

Token list registers expand more quickly, so if it suits you, you could also do:

\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

Repeating in an expendable way using e-tex additions (from 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
share|improve this answer
    
Yes, but not expandable. Ok, it isn't really necessary in the majority of the cases. –  Martin Scharrer Apr 19 '11 at 20:54
    
What does it mean not being expandable? –  Christian Lindig Apr 20 '11 at 5:52
    
Christian forgot to notify @Martin I guess, since I don't know the answer to that question. –  morbusg Apr 20 '11 at 7:06
    
@Christian: Something is expandable if you can use it inside an \edef or \write an TeX converts it fully to what you want. Assignments are not expandable, and so a loop using a count will not turn into a series of repeated commands inside an \edef. –  Joseph Wright Apr 20 '11 at 7:06
    
@Christian: I thought that the general question had been asked, but cannot find it. You might wish to ask about expandability in general, and those of us who understand it can try to explain! –  Joseph Wright Apr 20 '11 at 7:08

You can use the \foreach-command from PGF/TikZ.

\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}

For more information see the pgfmanual.pdf, section 56, pp. 504 an following.

There’s also a TeX-Way see e.g. this page (in german …)

share|improve this answer
1  
pgfs \foreach has the drawback that the command is executed in a group, which might be a big problem or none at all depending on the application. BTW: there is no reason the write {} after \cmd inside the loop, except if you have it as a placeholder for a possible argument (then you should write it as {...} as the OP did). –  Martin Scharrer Apr 19 '11 at 19:33
    
@MartinScharrer There’s no special reason why I used the {}. You’re right an I edited my post. Could you please outline a situation where the \foreach-group causes problems? –  Tobi Apr 19 '11 at 20:38
    
All assignments done in the loop will be executed in their own local group, which could have serious side effects depending on the code. Because you never known what code the user will use it is best to avoid these situations. –  Martin Scharrer Apr 19 '11 at 21:06
    
@MartinScharrer Thank’s. Maybe I remember that in case of getting problem with \foreachif not I’ll be back to ask here ;-) –  Tobi Apr 19 '11 at 21:57

Here some implementation I came up with which doesn't need any extra package. It uses \numexpr to avoid counters and is fully expandable.

\documentclass{article}

\makeatletter
\newcommand{\Repeat}[1]{%
    \expandafter\@Repeat\expandafter{\the\numexpr #1\relax}%
}

\def\@Repeat#1{%
    \ifnum#1>0
        \expandafter\@@Repeat\expandafter{\the\numexpr #1-1\expandafter\relax\expandafter}%
    \else
        \expandafter\@gobble
    \fi
}
\def\@@Repeat#1#2{%
    \@Repeat{#1}{#2}#2%
}
\makeatother

\begin{document}

\Repeat{0}{test }

\Repeat{1}{test }

\Repeat{2}{test }

\Repeat{3}{test }

\Repeat{4}{test }

\Repeat{5}{test }

\edef\TEST{\Repeat{5}{test }}
\texttt{\meaning\TEST}

\end{document}
share|improve this answer
    
If you look at the LaTeX3 implementation, it's expandable even without needing e-TeX. This is some clever code that has been around for many years. –  Joseph Wright Apr 19 '11 at 20:33
    
@Joseph: I have a really hard time reading the expl3 code, but it looks like it needs e-TeX to me. It uses \int_eval:w a.k.a. \numexpr. –  TH. Apr 20 '11 at 7:42
    
@TH. The expl3 implementation does indeed need \numexpr, as that makes the nature of the 'number' you give be more flexible. However, the original version of this approach just uses \number, and thus no e-TeX. Later on today I'll post the code 'translated' to plain TeX as a separate answer. –  Joseph Wright Apr 20 '11 at 8:09
    
@TH. I've added the plain TeX code to my answer, avoiding e-TeX but explaining why it is used for the expl3 version. –  Joseph Wright Apr 20 '11 at 8:34
    
@Joseph: I see now, that's very clever! Thanks. (One of these days, I really just need to learn expl3.) –  TH. Apr 20 '11 at 8:49

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.