Repeat command n times?A command for making a string of charactersRepeat characters n timesHow to define a...
How to be diplomatic in refusing to write code that breaches the privacy of our users
Method to test if a number is a perfect power?
How to Reset Passwords on Multiple Websites Easily?
Unreliable Magic - Is it worth it?
I'm in charge of equipment buying but no one's ever happy with what I choose. How to fix this?
Go Pregnant or Go Home
Increase performance creating Mandelbrot set in python
Where does the Z80 processor start executing from?
What does "I’d sit this one out, Cap," imply or mean in the context?
What is the opposite of 'gravitas'?
when is out of tune ok?
Why, precisely, is argon used in neutrino experiments?
Why didn't Theresa May consult with Parliament before negotiating a deal with the EU?
Why are there no referendums in the US?
Why escape if the_content isnt?
Gears on left are inverse to gears on right?
What is the best translation for "slot" in the context of multiplayer video games?
How did Doctor Strange see the winning outcome in Avengers: Infinity War?
How can I kill an app using Terminal?
Integer addition + constant, is it a group?
How to check is there any negative term in a large list?
Applicability of Single Responsibility Principle
Would a high gravity rocky planet be guaranteed to have an atmosphere?
Sequence of Tenses: Translating the subjunctive
Repeat command n times?
A command for making a string of charactersRepeat characters n timesHow to define a parshape command with LaTeX?Beamer: including items only some slides using a relative syntaxTricks to make macros expandableelsarticle: Changing symbol used in tnoterefBox with Semicircular Parshape at Top and Bottomdatatool repeat rowHow to avoid the compilation of some of my newcommands in latexShort syntax for including multiple times the same pages in pdfpagesHow to define a command that returns different commands based on a parameterdatatool repeat rowRepeat geometry / body / object / shape in PGFplotsHow to repeat over all characters in a string?How to use macros to repeat math equations in different settingsRepeat characters n timesNew command like an arbitrary number of nested applications of some commandRepeat last environment by commandPassing next character to commandDefault value of command
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{...}
macros programming
add a comment |
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{...}
macros programming
1
Note thatrepeat
is already defined by LaTeX as end-macro forloop
.
– Martin Scharrer♦
Apr 19 '11 at 19:34
add a comment |
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{...}
macros programming
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{...}
macros programming
macros programming
edited Apr 19 '11 at 19:41
student
asked Apr 19 '11 at 19:17
studentstudent
12.4k24102176
12.4k24102176
1
Note thatrepeat
is already defined by LaTeX as end-macro forloop
.
– Martin Scharrer♦
Apr 19 '11 at 19:34
add a comment |
1
Note thatrepeat
is already defined by LaTeX as end-macro forloop
.
– Martin Scharrer♦
Apr 19 '11 at 19:34
1
1
Note that
repeat
is already defined by LaTeX as end-macro for loop
.– Martin Scharrer♦
Apr 19 '11 at 19:34
Note that
repeat
is already defined by LaTeX as end-macro for loop
.– Martin Scharrer♦
Apr 19 '11 at 19:34
add a comment |
8 Answers
8
active
oldest
votes
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 (originally by David Kastrup, modified somewhat by the rest of the team) is
catcode `@ = 11relax
longdefreplicate#1{%
romannumeral
expandafterreplicate@first@auxnumber#1%
endcsname
}
longdefreplicate@first@aux#1{%
csname replicate@first@#1replicate@aux
}
chardefrm@end=0 %
longexpandafterdefcsname replicate@first@-endcsname
#1{rm@endNegativeReplication}
longexpandafterdefcsname replicate@first@0endcsname
#1{rm@end}
longexpandafterdefcsname replicate@first@1endcsname
#1{rm@end #1}
longexpandafterdefcsname replicate@first@2endcsname
#1{rm@end #1#1}
longexpandafterdefcsname replicate@first@3endcsname
#1{rm@end #1#1#1}
longexpandafterdefcsname replicate@first@4endcsname
#1{rm@end #1#1#1#1}
longexpandafterdefcsname replicate@first@5endcsname
#1{rm@end #1#1#1#1#1}
longexpandafterdefcsname replicate@first@6endcsname
#1{rm@end #1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@7endcsname
#1{rm@end #1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@8endcsname
#1{rm@end #1#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@9endcsname
#1{rm@end #1#1#1#1#1#1#1#1#1}
defreplicate@aux#1{%
csname replicate@#1replicate@aux
}
longexpandafterdefcsname replicate@endcsname#1{endcsname}
longexpandafterdefcsname replicate@0endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}}
longexpandafterdefcsname replicate@1endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1}
longexpandafterdefcsname replicate@2endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1}
longexpandafterdefcsname replicate@3endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1}
longexpandafterdefcsname replicate@4endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1}
longexpandafterdefcsname replicate@5endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1}
longexpandafterdefcsname replicate@6endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1}
longexpandafterdefcsname replicate@7endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@8endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@9endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1#1#1}
catcode `@ = 12relax
edeftest{replicate{20}{abc}}
showtest
bye
In the expl3
version, the number#1
is (effectively) replaced by numbernumexpr#1relax
, 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 expandable approach is to use romannumeral
, for example
catcode `@ = 11relax
defreplicate#1{%
expandafterreplicate@auxromannumeralnumber #1000Q{}
}
defreplicate@aux#1{csname replicate@aux@#1endcsname}
longdefreplicate@aux@m#1Q#2#3{replicate@aux#1Q{#2#3}{#3}}
longdefreplicate@aux@Q#1#2{#1}
edeftest{replicate{5}{a}}
showtest
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.
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
2
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 isprg_replicate:nn {10000}{prg_replicate:nn {10000}{...}}
. Not needed often.
– Bruno Le Floch
May 13 '11 at 8:41
|
show 1 more comment
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 …)
4
pgf
sforeach
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{}
aftercmd
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
1
@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 theforeach
-group causes problems?
– Tobi
Apr 19 '11 at 20:38
1
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 withforeach
if not I’ll be back to ask here ;-)
– Tobi
Apr 19 '11 at 21:57
I tried to place multiple tickets on a paper using theticket
package and theforeach
loop. It failed. All tickets are printed at the same location.
– Lemming
Jul 27 '17 at 9:35
|
show 2 more comments
multido
has a simple interface for replication:
documentclass{article}
usepackage{multido}
newcommand{cmd}{-x-}
newcommand{Repeat}{multido{i=1+1}}
begin{document}
Repeat{6}{cmd}
end{document}
1
This is an old answer, but I want just to mention thati=1+1
is useless here,newcommand{Repeat}{multido{}}
is enough.
– Kpym
Apr 29 '18 at 19:47
add a comment |
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@Repeatexpandafter{thenumexpr #1relax}%
}
def@Repeat#1{%
ifnum#1>0
expandafter@@Repeatexpandafter{thenumexpr #1-1expandafterrelaxexpandafter}%
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 }
edefTEST{Repeat{5}{test }}
texttt{meaningTEST}
end{document}
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 theexpl3
code, but it looks like it needs e-TeX to me. It usesint_eval:w
a.k.a.numexpr
.
– TH.
Apr 20 '11 at 7:42
@TH. Theexpl3
implementation does indeed neednumexpr
, as that makes the nature of the 'number' you give be more flexible. However, the original version of this approach just usesnumber
, 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 theexpl3
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 learnexpl3
.)
– TH.
Apr 20 '11 at 8:49
|
show 3 more comments
Plain and simple (pun intended):
deffoo{keke}
defbar#1#2{count0=#1 loop ifnumcount0>0 advancecount0 by -1 #2repeat}
bar3foo % results in kekekekekeke
bye
Token list registers expand more quickly, so if it suits you, you could also do:
newtoksfoo foo={keke}
defbar#1#2{count0=#1 loop ifnumcount0>0 advancecount0 by -1 the#2repeat}
bar3foo % results in kekekekekeke
bye
Repeating in an expendable way using e-tex additions (from http://www.tug.org/TUGboat/tb29-2/tb92jackowski.pdf):
deffoo{keke}
defgobbleone#1{}
longdefreplicate#1#2{%
ifnumnumexpr#1>0
#2expandafterreplicateexpandafter
{numbernumexpr#1-1expandafter}%
else
expandaftergobbleone
fi{#2}}
replicate3foo % results in kekekekekeke
bye
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
1
@Christian: Something is expandable if you can use it inside anedef
orwrite
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 anedef
.
– 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
|
show 1 more comment
Of course, the simple answer to the OP is: use loop
. But there are more codes here signed as "clever", if the loop is done only at expand processor level. And more "clever" codes here do this without using of eTeX primitives.
So, I give two codes here. You can explore them from "cleverness" point of view:).
First code uses known trick with romannumeral #1000
which expands to #1 "em"s and then we do loop over these "em"s over input stream. The main difference from the similar code presented here by @Joseph is that we needn't to read whole long sequence of "em"s again and again:
defreplicate#1{expandafterrepUexpandafter{romannumeralnumber#1000}}
defrepU#1#2{repV{#2}#1;}
defrepV#1#2{ifx#2;else#1fihererepV{#1}fi}
deffihere#1fi{fi#1}
message{replicate{27}{abc}}
bye
The second code is inspired by second code presented here by @Joseph where each decimal digit is processed individually. The code (in the accepted answer) uses nested csname
s. I do the same without nested csname
s and the code is more compact. Of course, it works at expand processor level without any need of eTeX primitives:
defreplicate#1{expandafterrepAnumber#1;;}
defrepA#1#2;#3;{ifx;#2;repB#1#3fi repA#2;#1#3;}
defrepB#1fi#2;#3;{firepC{#1}}
defrepC#1#2{repD{#2}#1;}
defrepD#1#2{ifx#2;else repE{#1}#2fi}
defrepE#1#2fi{fi repF#2{#1}repD{repF{10}{#1}}}
defrepF#1#2{ifcase#1 or#2or#2#2or#2#2#2or#2#2#2#2or#2#2#2#2#2or
#2#2#2#2#2#2or#2#2#2#2#2#2#2or#2#2#2#2#2#2#2#2or
#2#2#2#2#2#2#2#2#2or#2#2#2#2#2#2#2#2#2#2fi}
message{replicate{27}{abc}}
bye
My comment about eTeX was probably misleading: I've removed it (you need eTeX if you want to accept integer expressions for the number of repeats, not for the core idea of making copies).
– Joseph Wright♦
Mar 21 '16 at 10:20
nice but it should be pointed out this doesn't expand fully underromannumeral-`0
.
– user4686
Mar 22 '16 at 22:24
add a comment |
Here is an example with loop and newcommand:
documentclass{article}
newcounter{z}
newcommandy[2]{
loop ifnumvalue{z} < #1
#2%
stepcounter{z}%
repeat
}
begin{document}
y{10}{Hello}
end{document}
The request is to repeat a command
– Andrew Swann
Mar 20 '16 at 15:11
Only the simplest commands - e.g. if the new command defines other commands the grouping is not equivalent.
– Andrew Swann
Mar 20 '16 at 15:23
Isn't this the same as the first suggestion in @morbusg's answer?
– clemens
Mar 20 '16 at 15:27
add a comment |
I tried an alternative to the clever csname
governed expansion from Joseph's answer borrowed from expl3 code.
eTeX is used only to allow input to be an expression: else replace thenumexpr
at the start by number
.
This is less efficient than the David Kastrup + LaTeX team code, although perhaps it becomes about the same when the number of replications is in the thousands (not much tested).
The initial version of this answer had more complicated code which was at about the same level of efficiency. There was an unfortunate chardefz@=0
in that code, which is very wrong and I don't know why it was there.
This answer handles more efficiently than Joseph's the case of a negative asked for number of replication.
It could be easily reworked into a macro (working only in a edef
) leaving tokens behind it rather than in front of it while expanding.
catcode`@ 11
defJFsignfork #10-#2#3krof {#2}
%chardefz@ 0 % NO! z@ is a dimen in TeX/LaTeX
defJFrep #1{romannumeralexpandafterJFrep@athenumexpr #1;3456789XY!}%
defJFrep@a #1{JFsignfork
#1-JFrep@nil
0#1JFrep@neg
0-JFrep@b
krof #1%
}%
longdefJFrep@nil #1!#2{z@}
longdefJFrep@neg #1!#2{z@NegativeReplication}
% TeX numbers have at most 10 digits
defJFrep@b #1#2#3#4#5#6#7#8#9{JFrep@c {.#9.#8.#7.#6.#5.#4.#3.#2;#1}}
defJFrep@c #1#2#3#4!{JFrep@d .#3.#2#1!}
defJFrep@d #1;#2#3{csname JFrep@f#2#3endcsname}
longexpandafterdefcsname JFrep@f.0endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}}%
longexpandafterdefcsname JFrep@f.1endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4}%
longexpandafterdefcsname JFrep@f.2endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4}%
longexpandafterdefcsname JFrep@f.3endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4}%
longexpandafterdefcsname JFrep@f.4endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4}%
longexpandafterdefcsname JFrep@f.5endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.6endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.7endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.8endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.9endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f;1endcsname!#1{z@#1}%
longexpandafterdefcsname JFrep@f;2endcsname!#1{z@#1#1}%
longexpandafterdefcsname JFrep@f;3endcsname!#1{z@#1#1#1}%
longexpandafterdefcsname JFrep@f;4endcsname!#1{z@#1#1#1#1}%
longexpandafterdefcsname JFrep@f;5endcsname!#1{z@#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;6endcsname!#1{z@#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;7endcsname!#1{z@#1#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;8endcsname!#1{z@#1#1#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;9endcsname!#1{z@#1#1#1#1#1#1#1#1#1}%
catcode`@ 12
edeftest{JFrep{123}{abc}}
showtest
bye
There is now anxintreplicate
in xint but it is a clone of the expl3's code with very minor changes, it is not the code of this answer...
– user4686
Apr 29 '18 at 20:26
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "85"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f16189%2frepeat-command-n-times%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
8 Answers
8
active
oldest
votes
8 Answers
8
active
oldest
votes
active
oldest
votes
active
oldest
votes
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 (originally by David Kastrup, modified somewhat by the rest of the team) is
catcode `@ = 11relax
longdefreplicate#1{%
romannumeral
expandafterreplicate@first@auxnumber#1%
endcsname
}
longdefreplicate@first@aux#1{%
csname replicate@first@#1replicate@aux
}
chardefrm@end=0 %
longexpandafterdefcsname replicate@first@-endcsname
#1{rm@endNegativeReplication}
longexpandafterdefcsname replicate@first@0endcsname
#1{rm@end}
longexpandafterdefcsname replicate@first@1endcsname
#1{rm@end #1}
longexpandafterdefcsname replicate@first@2endcsname
#1{rm@end #1#1}
longexpandafterdefcsname replicate@first@3endcsname
#1{rm@end #1#1#1}
longexpandafterdefcsname replicate@first@4endcsname
#1{rm@end #1#1#1#1}
longexpandafterdefcsname replicate@first@5endcsname
#1{rm@end #1#1#1#1#1}
longexpandafterdefcsname replicate@first@6endcsname
#1{rm@end #1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@7endcsname
#1{rm@end #1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@8endcsname
#1{rm@end #1#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@9endcsname
#1{rm@end #1#1#1#1#1#1#1#1#1}
defreplicate@aux#1{%
csname replicate@#1replicate@aux
}
longexpandafterdefcsname replicate@endcsname#1{endcsname}
longexpandafterdefcsname replicate@0endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}}
longexpandafterdefcsname replicate@1endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1}
longexpandafterdefcsname replicate@2endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1}
longexpandafterdefcsname replicate@3endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1}
longexpandafterdefcsname replicate@4endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1}
longexpandafterdefcsname replicate@5endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1}
longexpandafterdefcsname replicate@6endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1}
longexpandafterdefcsname replicate@7endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@8endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@9endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1#1#1}
catcode `@ = 12relax
edeftest{replicate{20}{abc}}
showtest
bye
In the expl3
version, the number#1
is (effectively) replaced by numbernumexpr#1relax
, 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 expandable approach is to use romannumeral
, for example
catcode `@ = 11relax
defreplicate#1{%
expandafterreplicate@auxromannumeralnumber #1000Q{}
}
defreplicate@aux#1{csname replicate@aux@#1endcsname}
longdefreplicate@aux@m#1Q#2#3{replicate@aux#1Q{#2#3}{#3}}
longdefreplicate@aux@Q#1#2{#1}
edeftest{replicate{5}{a}}
showtest
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.
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
2
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 isprg_replicate:nn {10000}{prg_replicate:nn {10000}{...}}
. Not needed often.
– Bruno Le Floch
May 13 '11 at 8:41
|
show 1 more comment
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 (originally by David Kastrup, modified somewhat by the rest of the team) is
catcode `@ = 11relax
longdefreplicate#1{%
romannumeral
expandafterreplicate@first@auxnumber#1%
endcsname
}
longdefreplicate@first@aux#1{%
csname replicate@first@#1replicate@aux
}
chardefrm@end=0 %
longexpandafterdefcsname replicate@first@-endcsname
#1{rm@endNegativeReplication}
longexpandafterdefcsname replicate@first@0endcsname
#1{rm@end}
longexpandafterdefcsname replicate@first@1endcsname
#1{rm@end #1}
longexpandafterdefcsname replicate@first@2endcsname
#1{rm@end #1#1}
longexpandafterdefcsname replicate@first@3endcsname
#1{rm@end #1#1#1}
longexpandafterdefcsname replicate@first@4endcsname
#1{rm@end #1#1#1#1}
longexpandafterdefcsname replicate@first@5endcsname
#1{rm@end #1#1#1#1#1}
longexpandafterdefcsname replicate@first@6endcsname
#1{rm@end #1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@7endcsname
#1{rm@end #1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@8endcsname
#1{rm@end #1#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@9endcsname
#1{rm@end #1#1#1#1#1#1#1#1#1}
defreplicate@aux#1{%
csname replicate@#1replicate@aux
}
longexpandafterdefcsname replicate@endcsname#1{endcsname}
longexpandafterdefcsname replicate@0endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}}
longexpandafterdefcsname replicate@1endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1}
longexpandafterdefcsname replicate@2endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1}
longexpandafterdefcsname replicate@3endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1}
longexpandafterdefcsname replicate@4endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1}
longexpandafterdefcsname replicate@5endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1}
longexpandafterdefcsname replicate@6endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1}
longexpandafterdefcsname replicate@7endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@8endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@9endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1#1#1}
catcode `@ = 12relax
edeftest{replicate{20}{abc}}
showtest
bye
In the expl3
version, the number#1
is (effectively) replaced by numbernumexpr#1relax
, 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 expandable approach is to use romannumeral
, for example
catcode `@ = 11relax
defreplicate#1{%
expandafterreplicate@auxromannumeralnumber #1000Q{}
}
defreplicate@aux#1{csname replicate@aux@#1endcsname}
longdefreplicate@aux@m#1Q#2#3{replicate@aux#1Q{#2#3}{#3}}
longdefreplicate@aux@Q#1#2{#1}
edeftest{replicate{5}{a}}
showtest
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.
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
2
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 isprg_replicate:nn {10000}{prg_replicate:nn {10000}{...}}
. Not needed often.
– Bruno Le Floch
May 13 '11 at 8:41
|
show 1 more comment
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 (originally by David Kastrup, modified somewhat by the rest of the team) is
catcode `@ = 11relax
longdefreplicate#1{%
romannumeral
expandafterreplicate@first@auxnumber#1%
endcsname
}
longdefreplicate@first@aux#1{%
csname replicate@first@#1replicate@aux
}
chardefrm@end=0 %
longexpandafterdefcsname replicate@first@-endcsname
#1{rm@endNegativeReplication}
longexpandafterdefcsname replicate@first@0endcsname
#1{rm@end}
longexpandafterdefcsname replicate@first@1endcsname
#1{rm@end #1}
longexpandafterdefcsname replicate@first@2endcsname
#1{rm@end #1#1}
longexpandafterdefcsname replicate@first@3endcsname
#1{rm@end #1#1#1}
longexpandafterdefcsname replicate@first@4endcsname
#1{rm@end #1#1#1#1}
longexpandafterdefcsname replicate@first@5endcsname
#1{rm@end #1#1#1#1#1}
longexpandafterdefcsname replicate@first@6endcsname
#1{rm@end #1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@7endcsname
#1{rm@end #1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@8endcsname
#1{rm@end #1#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@9endcsname
#1{rm@end #1#1#1#1#1#1#1#1#1}
defreplicate@aux#1{%
csname replicate@#1replicate@aux
}
longexpandafterdefcsname replicate@endcsname#1{endcsname}
longexpandafterdefcsname replicate@0endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}}
longexpandafterdefcsname replicate@1endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1}
longexpandafterdefcsname replicate@2endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1}
longexpandafterdefcsname replicate@3endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1}
longexpandafterdefcsname replicate@4endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1}
longexpandafterdefcsname replicate@5endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1}
longexpandafterdefcsname replicate@6endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1}
longexpandafterdefcsname replicate@7endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@8endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@9endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1#1#1}
catcode `@ = 12relax
edeftest{replicate{20}{abc}}
showtest
bye
In the expl3
version, the number#1
is (effectively) replaced by numbernumexpr#1relax
, 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 expandable approach is to use romannumeral
, for example
catcode `@ = 11relax
defreplicate#1{%
expandafterreplicate@auxromannumeralnumber #1000Q{}
}
defreplicate@aux#1{csname replicate@aux@#1endcsname}
longdefreplicate@aux@m#1Q#2#3{replicate@aux#1Q{#2#3}{#3}}
longdefreplicate@aux@Q#1#2{#1}
edeftest{replicate{5}{a}}
showtest
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.
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 (originally by David Kastrup, modified somewhat by the rest of the team) is
catcode `@ = 11relax
longdefreplicate#1{%
romannumeral
expandafterreplicate@first@auxnumber#1%
endcsname
}
longdefreplicate@first@aux#1{%
csname replicate@first@#1replicate@aux
}
chardefrm@end=0 %
longexpandafterdefcsname replicate@first@-endcsname
#1{rm@endNegativeReplication}
longexpandafterdefcsname replicate@first@0endcsname
#1{rm@end}
longexpandafterdefcsname replicate@first@1endcsname
#1{rm@end #1}
longexpandafterdefcsname replicate@first@2endcsname
#1{rm@end #1#1}
longexpandafterdefcsname replicate@first@3endcsname
#1{rm@end #1#1#1}
longexpandafterdefcsname replicate@first@4endcsname
#1{rm@end #1#1#1#1}
longexpandafterdefcsname replicate@first@5endcsname
#1{rm@end #1#1#1#1#1}
longexpandafterdefcsname replicate@first@6endcsname
#1{rm@end #1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@7endcsname
#1{rm@end #1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@8endcsname
#1{rm@end #1#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@first@9endcsname
#1{rm@end #1#1#1#1#1#1#1#1#1}
defreplicate@aux#1{%
csname replicate@#1replicate@aux
}
longexpandafterdefcsname replicate@endcsname#1{endcsname}
longexpandafterdefcsname replicate@0endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}}
longexpandafterdefcsname replicate@1endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1}
longexpandafterdefcsname replicate@2endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1}
longexpandafterdefcsname replicate@3endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1}
longexpandafterdefcsname replicate@4endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1}
longexpandafterdefcsname replicate@5endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1}
longexpandafterdefcsname replicate@6endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1}
longexpandafterdefcsname replicate@7endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@8endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1#1}
longexpandafterdefcsname replicate@9endcsname
#1{endcsname{#1#1#1#1#1#1#1#1#1#1}#1#1#1#1#1#1#1#1#1}
catcode `@ = 12relax
edeftest{replicate{20}{abc}}
showtest
bye
In the expl3
version, the number#1
is (effectively) replaced by numbernumexpr#1relax
, 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 expandable approach is to use romannumeral
, for example
catcode `@ = 11relax
defreplicate#1{%
expandafterreplicate@auxromannumeralnumber #1000Q{}
}
defreplicate@aux#1{csname replicate@aux@#1endcsname}
longdefreplicate@aux@m#1Q#2#3{replicate@aux#1Q{#2#3}{#3}}
longdefreplicate@aux@Q#1#2{#1}
edeftest{replicate{5}{a}}
showtest
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.
edited 2 mins ago
Faheem Mitha
3,30653964
3,30653964
answered Apr 19 '11 at 19:40
Joseph Wright♦Joseph Wright
205k23562890
205k23562890
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
2
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 isprg_replicate:nn {10000}{prg_replicate:nn {10000}{...}}
. Not needed often.
– Bruno Le Floch
May 13 '11 at 8:41
|
show 1 more comment
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
2
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 isprg_replicate:nn {10000}{prg_replicate:nn {10000}{...}}
. Not needed often.
– Bruno Le Floch
May 13 '11 at 8:41
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
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
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
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
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
2
2
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
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
|
show 1 more comment
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 …)
4
pgf
sforeach
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{}
aftercmd
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
1
@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 theforeach
-group causes problems?
– Tobi
Apr 19 '11 at 20:38
1
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 withforeach
if not I’ll be back to ask here ;-)
– Tobi
Apr 19 '11 at 21:57
I tried to place multiple tickets on a paper using theticket
package and theforeach
loop. It failed. All tickets are printed at the same location.
– Lemming
Jul 27 '17 at 9:35
|
show 2 more comments
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 …)
4
pgf
sforeach
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{}
aftercmd
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
1
@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 theforeach
-group causes problems?
– Tobi
Apr 19 '11 at 20:38
1
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 withforeach
if not I’ll be back to ask here ;-)
– Tobi
Apr 19 '11 at 21:57
I tried to place multiple tickets on a paper using theticket
package and theforeach
loop. It failed. All tickets are printed at the same location.
– Lemming
Jul 27 '17 at 9:35
|
show 2 more comments
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 …)
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 …)
edited Apr 19 '11 at 20:38
answered Apr 19 '11 at 19:19
TobiTobi
38.6k8131261
38.6k8131261
4
pgf
sforeach
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{}
aftercmd
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
1
@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 theforeach
-group causes problems?
– Tobi
Apr 19 '11 at 20:38
1
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 withforeach
if not I’ll be back to ask here ;-)
– Tobi
Apr 19 '11 at 21:57
I tried to place multiple tickets on a paper using theticket
package and theforeach
loop. It failed. All tickets are printed at the same location.
– Lemming
Jul 27 '17 at 9:35
|
show 2 more comments
4
pgf
sforeach
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{}
aftercmd
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
1
@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 theforeach
-group causes problems?
– Tobi
Apr 19 '11 at 20:38
1
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 withforeach
if not I’ll be back to ask here ;-)
– Tobi
Apr 19 '11 at 21:57
I tried to place multiple tickets on a paper using theticket
package and theforeach
loop. It failed. All tickets are printed at the same location.
– Lemming
Jul 27 '17 at 9:35
4
4
pgf
s 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
pgf
s 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
1
1
@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
@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
1
1
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
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
foreach
if not I’ll be back to ask here ;-)– Tobi
Apr 19 '11 at 21:57
@MartinScharrer Thank’s. Maybe I remember that in case of getting problem with
foreach
if not I’ll be back to ask here ;-)– Tobi
Apr 19 '11 at 21:57
I tried to place multiple tickets on a paper using the
ticket
package and the foreach
loop. It failed. All tickets are printed at the same location.– Lemming
Jul 27 '17 at 9:35
I tried to place multiple tickets on a paper using the
ticket
package and the foreach
loop. It failed. All tickets are printed at the same location.– Lemming
Jul 27 '17 at 9:35
|
show 2 more comments
multido
has a simple interface for replication:
documentclass{article}
usepackage{multido}
newcommand{cmd}{-x-}
newcommand{Repeat}{multido{i=1+1}}
begin{document}
Repeat{6}{cmd}
end{document}
1
This is an old answer, but I want just to mention thati=1+1
is useless here,newcommand{Repeat}{multido{}}
is enough.
– Kpym
Apr 29 '18 at 19:47
add a comment |
multido
has a simple interface for replication:
documentclass{article}
usepackage{multido}
newcommand{cmd}{-x-}
newcommand{Repeat}{multido{i=1+1}}
begin{document}
Repeat{6}{cmd}
end{document}
1
This is an old answer, but I want just to mention thati=1+1
is useless here,newcommand{Repeat}{multido{}}
is enough.
– Kpym
Apr 29 '18 at 19:47
add a comment |
multido
has a simple interface for replication:
documentclass{article}
usepackage{multido}
newcommand{cmd}{-x-}
newcommand{Repeat}{multido{i=1+1}}
begin{document}
Repeat{6}{cmd}
end{document}
multido
has a simple interface for replication:
documentclass{article}
usepackage{multido}
newcommand{cmd}{-x-}
newcommand{Repeat}{multido{i=1+1}}
begin{document}
Repeat{6}{cmd}
end{document}
answered Nov 12 '14 at 6:52
WernerWerner
449k719941699
449k719941699
1
This is an old answer, but I want just to mention thati=1+1
is useless here,newcommand{Repeat}{multido{}}
is enough.
– Kpym
Apr 29 '18 at 19:47
add a comment |
1
This is an old answer, but I want just to mention thati=1+1
is useless here,newcommand{Repeat}{multido{}}
is enough.
– Kpym
Apr 29 '18 at 19:47
1
1
This is an old answer, but I want just to mention that
i=1+1
is useless here, newcommand{Repeat}{multido{}}
is enough.– Kpym
Apr 29 '18 at 19:47
This is an old answer, but I want just to mention that
i=1+1
is useless here, newcommand{Repeat}{multido{}}
is enough.– Kpym
Apr 29 '18 at 19:47
add a comment |
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@Repeatexpandafter{thenumexpr #1relax}%
}
def@Repeat#1{%
ifnum#1>0
expandafter@@Repeatexpandafter{thenumexpr #1-1expandafterrelaxexpandafter}%
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 }
edefTEST{Repeat{5}{test }}
texttt{meaningTEST}
end{document}
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 theexpl3
code, but it looks like it needs e-TeX to me. It usesint_eval:w
a.k.a.numexpr
.
– TH.
Apr 20 '11 at 7:42
@TH. Theexpl3
implementation does indeed neednumexpr
, as that makes the nature of the 'number' you give be more flexible. However, the original version of this approach just usesnumber
, 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 theexpl3
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 learnexpl3
.)
– TH.
Apr 20 '11 at 8:49
|
show 3 more comments
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@Repeatexpandafter{thenumexpr #1relax}%
}
def@Repeat#1{%
ifnum#1>0
expandafter@@Repeatexpandafter{thenumexpr #1-1expandafterrelaxexpandafter}%
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 }
edefTEST{Repeat{5}{test }}
texttt{meaningTEST}
end{document}
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 theexpl3
code, but it looks like it needs e-TeX to me. It usesint_eval:w
a.k.a.numexpr
.
– TH.
Apr 20 '11 at 7:42
@TH. Theexpl3
implementation does indeed neednumexpr
, as that makes the nature of the 'number' you give be more flexible. However, the original version of this approach just usesnumber
, 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 theexpl3
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 learnexpl3
.)
– TH.
Apr 20 '11 at 8:49
|
show 3 more comments
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@Repeatexpandafter{thenumexpr #1relax}%
}
def@Repeat#1{%
ifnum#1>0
expandafter@@Repeatexpandafter{thenumexpr #1-1expandafterrelaxexpandafter}%
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 }
edefTEST{Repeat{5}{test }}
texttt{meaningTEST}
end{document}
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@Repeatexpandafter{thenumexpr #1relax}%
}
def@Repeat#1{%
ifnum#1>0
expandafter@@Repeatexpandafter{thenumexpr #1-1expandafterrelaxexpandafter}%
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 }
edefTEST{Repeat{5}{test }}
texttt{meaningTEST}
end{document}
answered Apr 19 '11 at 19:55
Martin Scharrer♦Martin Scharrer
203k47651825
203k47651825
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 theexpl3
code, but it looks like it needs e-TeX to me. It usesint_eval:w
a.k.a.numexpr
.
– TH.
Apr 20 '11 at 7:42
@TH. Theexpl3
implementation does indeed neednumexpr
, as that makes the nature of the 'number' you give be more flexible. However, the original version of this approach just usesnumber
, 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 theexpl3
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 learnexpl3
.)
– TH.
Apr 20 '11 at 8:49
|
show 3 more comments
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 theexpl3
code, but it looks like it needs e-TeX to me. It usesint_eval:w
a.k.a.numexpr
.
– TH.
Apr 20 '11 at 7:42
@TH. Theexpl3
implementation does indeed neednumexpr
, as that makes the nature of the 'number' you give be more flexible. However, the original version of this approach just usesnumber
, 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 theexpl3
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 learnexpl3
.)
– TH.
Apr 20 '11 at 8:49
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
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
@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. 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
@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
@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
|
show 3 more comments
Plain and simple (pun intended):
deffoo{keke}
defbar#1#2{count0=#1 loop ifnumcount0>0 advancecount0 by -1 #2repeat}
bar3foo % results in kekekekekeke
bye
Token list registers expand more quickly, so if it suits you, you could also do:
newtoksfoo foo={keke}
defbar#1#2{count0=#1 loop ifnumcount0>0 advancecount0 by -1 the#2repeat}
bar3foo % results in kekekekekeke
bye
Repeating in an expendable way using e-tex additions (from http://www.tug.org/TUGboat/tb29-2/tb92jackowski.pdf):
deffoo{keke}
defgobbleone#1{}
longdefreplicate#1#2{%
ifnumnumexpr#1>0
#2expandafterreplicateexpandafter
{numbernumexpr#1-1expandafter}%
else
expandaftergobbleone
fi{#2}}
replicate3foo % results in kekekekekeke
bye
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
1
@Christian: Something is expandable if you can use it inside anedef
orwrite
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 anedef
.
– 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
|
show 1 more comment
Plain and simple (pun intended):
deffoo{keke}
defbar#1#2{count0=#1 loop ifnumcount0>0 advancecount0 by -1 #2repeat}
bar3foo % results in kekekekekeke
bye
Token list registers expand more quickly, so if it suits you, you could also do:
newtoksfoo foo={keke}
defbar#1#2{count0=#1 loop ifnumcount0>0 advancecount0 by -1 the#2repeat}
bar3foo % results in kekekekekeke
bye
Repeating in an expendable way using e-tex additions (from http://www.tug.org/TUGboat/tb29-2/tb92jackowski.pdf):
deffoo{keke}
defgobbleone#1{}
longdefreplicate#1#2{%
ifnumnumexpr#1>0
#2expandafterreplicateexpandafter
{numbernumexpr#1-1expandafter}%
else
expandaftergobbleone
fi{#2}}
replicate3foo % results in kekekekekeke
bye
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
1
@Christian: Something is expandable if you can use it inside anedef
orwrite
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 anedef
.
– 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
|
show 1 more comment
Plain and simple (pun intended):
deffoo{keke}
defbar#1#2{count0=#1 loop ifnumcount0>0 advancecount0 by -1 #2repeat}
bar3foo % results in kekekekekeke
bye
Token list registers expand more quickly, so if it suits you, you could also do:
newtoksfoo foo={keke}
defbar#1#2{count0=#1 loop ifnumcount0>0 advancecount0 by -1 the#2repeat}
bar3foo % results in kekekekekeke
bye
Repeating in an expendable way using e-tex additions (from http://www.tug.org/TUGboat/tb29-2/tb92jackowski.pdf):
deffoo{keke}
defgobbleone#1{}
longdefreplicate#1#2{%
ifnumnumexpr#1>0
#2expandafterreplicateexpandafter
{numbernumexpr#1-1expandafter}%
else
expandaftergobbleone
fi{#2}}
replicate3foo % results in kekekekekeke
bye
Plain and simple (pun intended):
deffoo{keke}
defbar#1#2{count0=#1 loop ifnumcount0>0 advancecount0 by -1 #2repeat}
bar3foo % results in kekekekekeke
bye
Token list registers expand more quickly, so if it suits you, you could also do:
newtoksfoo foo={keke}
defbar#1#2{count0=#1 loop ifnumcount0>0 advancecount0 by -1 the#2repeat}
bar3foo % results in kekekekekeke
bye
Repeating in an expendable way using e-tex additions (from http://www.tug.org/TUGboat/tb29-2/tb92jackowski.pdf):
deffoo{keke}
defgobbleone#1{}
longdefreplicate#1#2{%
ifnumnumexpr#1>0
#2expandafterreplicateexpandafter
{numbernumexpr#1-1expandafter}%
else
expandaftergobbleone
fi{#2}}
replicate3foo % results in kekekekekeke
bye
edited Apr 20 '11 at 7:45
answered Apr 19 '11 at 20:27
morbusgmorbusg
20.3k362138
20.3k362138
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
1
@Christian: Something is expandable if you can use it inside anedef
orwrite
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 anedef
.
– 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
|
show 1 more comment
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
1
@Christian: Something is expandable if you can use it inside anedef
orwrite
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 anedef
.
– 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
Yes, but not expandable. Ok, it isn't really necessary in the majority of the cases.
– Martin Scharrer♦
Apr 19 '11 at 20:54
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
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 forgot to notify @Martin I guess, since I don't know the answer to that question.
– morbusg
Apr 20 '11 at 7:06
1
1
@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: 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
@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
|
show 1 more comment
Of course, the simple answer to the OP is: use loop
. But there are more codes here signed as "clever", if the loop is done only at expand processor level. And more "clever" codes here do this without using of eTeX primitives.
So, I give two codes here. You can explore them from "cleverness" point of view:).
First code uses known trick with romannumeral #1000
which expands to #1 "em"s and then we do loop over these "em"s over input stream. The main difference from the similar code presented here by @Joseph is that we needn't to read whole long sequence of "em"s again and again:
defreplicate#1{expandafterrepUexpandafter{romannumeralnumber#1000}}
defrepU#1#2{repV{#2}#1;}
defrepV#1#2{ifx#2;else#1fihererepV{#1}fi}
deffihere#1fi{fi#1}
message{replicate{27}{abc}}
bye
The second code is inspired by second code presented here by @Joseph where each decimal digit is processed individually. The code (in the accepted answer) uses nested csname
s. I do the same without nested csname
s and the code is more compact. Of course, it works at expand processor level without any need of eTeX primitives:
defreplicate#1{expandafterrepAnumber#1;;}
defrepA#1#2;#3;{ifx;#2;repB#1#3fi repA#2;#1#3;}
defrepB#1fi#2;#3;{firepC{#1}}
defrepC#1#2{repD{#2}#1;}
defrepD#1#2{ifx#2;else repE{#1}#2fi}
defrepE#1#2fi{fi repF#2{#1}repD{repF{10}{#1}}}
defrepF#1#2{ifcase#1 or#2or#2#2or#2#2#2or#2#2#2#2or#2#2#2#2#2or
#2#2#2#2#2#2or#2#2#2#2#2#2#2or#2#2#2#2#2#2#2#2or
#2#2#2#2#2#2#2#2#2or#2#2#2#2#2#2#2#2#2#2fi}
message{replicate{27}{abc}}
bye
My comment about eTeX was probably misleading: I've removed it (you need eTeX if you want to accept integer expressions for the number of repeats, not for the core idea of making copies).
– Joseph Wright♦
Mar 21 '16 at 10:20
nice but it should be pointed out this doesn't expand fully underromannumeral-`0
.
– user4686
Mar 22 '16 at 22:24
add a comment |
Of course, the simple answer to the OP is: use loop
. But there are more codes here signed as "clever", if the loop is done only at expand processor level. And more "clever" codes here do this without using of eTeX primitives.
So, I give two codes here. You can explore them from "cleverness" point of view:).
First code uses known trick with romannumeral #1000
which expands to #1 "em"s and then we do loop over these "em"s over input stream. The main difference from the similar code presented here by @Joseph is that we needn't to read whole long sequence of "em"s again and again:
defreplicate#1{expandafterrepUexpandafter{romannumeralnumber#1000}}
defrepU#1#2{repV{#2}#1;}
defrepV#1#2{ifx#2;else#1fihererepV{#1}fi}
deffihere#1fi{fi#1}
message{replicate{27}{abc}}
bye
The second code is inspired by second code presented here by @Joseph where each decimal digit is processed individually. The code (in the accepted answer) uses nested csname
s. I do the same without nested csname
s and the code is more compact. Of course, it works at expand processor level without any need of eTeX primitives:
defreplicate#1{expandafterrepAnumber#1;;}
defrepA#1#2;#3;{ifx;#2;repB#1#3fi repA#2;#1#3;}
defrepB#1fi#2;#3;{firepC{#1}}
defrepC#1#2{repD{#2}#1;}
defrepD#1#2{ifx#2;else repE{#1}#2fi}
defrepE#1#2fi{fi repF#2{#1}repD{repF{10}{#1}}}
defrepF#1#2{ifcase#1 or#2or#2#2or#2#2#2or#2#2#2#2or#2#2#2#2#2or
#2#2#2#2#2#2or#2#2#2#2#2#2#2or#2#2#2#2#2#2#2#2or
#2#2#2#2#2#2#2#2#2or#2#2#2#2#2#2#2#2#2#2fi}
message{replicate{27}{abc}}
bye
My comment about eTeX was probably misleading: I've removed it (you need eTeX if you want to accept integer expressions for the number of repeats, not for the core idea of making copies).
– Joseph Wright♦
Mar 21 '16 at 10:20
nice but it should be pointed out this doesn't expand fully underromannumeral-`0
.
– user4686
Mar 22 '16 at 22:24
add a comment |
Of course, the simple answer to the OP is: use loop
. But there are more codes here signed as "clever", if the loop is done only at expand processor level. And more "clever" codes here do this without using of eTeX primitives.
So, I give two codes here. You can explore them from "cleverness" point of view:).
First code uses known trick with romannumeral #1000
which expands to #1 "em"s and then we do loop over these "em"s over input stream. The main difference from the similar code presented here by @Joseph is that we needn't to read whole long sequence of "em"s again and again:
defreplicate#1{expandafterrepUexpandafter{romannumeralnumber#1000}}
defrepU#1#2{repV{#2}#1;}
defrepV#1#2{ifx#2;else#1fihererepV{#1}fi}
deffihere#1fi{fi#1}
message{replicate{27}{abc}}
bye
The second code is inspired by second code presented here by @Joseph where each decimal digit is processed individually. The code (in the accepted answer) uses nested csname
s. I do the same without nested csname
s and the code is more compact. Of course, it works at expand processor level without any need of eTeX primitives:
defreplicate#1{expandafterrepAnumber#1;;}
defrepA#1#2;#3;{ifx;#2;repB#1#3fi repA#2;#1#3;}
defrepB#1fi#2;#3;{firepC{#1}}
defrepC#1#2{repD{#2}#1;}
defrepD#1#2{ifx#2;else repE{#1}#2fi}
defrepE#1#2fi{fi repF#2{#1}repD{repF{10}{#1}}}
defrepF#1#2{ifcase#1 or#2or#2#2or#2#2#2or#2#2#2#2or#2#2#2#2#2or
#2#2#2#2#2#2or#2#2#2#2#2#2#2or#2#2#2#2#2#2#2#2or
#2#2#2#2#2#2#2#2#2or#2#2#2#2#2#2#2#2#2#2fi}
message{replicate{27}{abc}}
bye
Of course, the simple answer to the OP is: use loop
. But there are more codes here signed as "clever", if the loop is done only at expand processor level. And more "clever" codes here do this without using of eTeX primitives.
So, I give two codes here. You can explore them from "cleverness" point of view:).
First code uses known trick with romannumeral #1000
which expands to #1 "em"s and then we do loop over these "em"s over input stream. The main difference from the similar code presented here by @Joseph is that we needn't to read whole long sequence of "em"s again and again:
defreplicate#1{expandafterrepUexpandafter{romannumeralnumber#1000}}
defrepU#1#2{repV{#2}#1;}
defrepV#1#2{ifx#2;else#1fihererepV{#1}fi}
deffihere#1fi{fi#1}
message{replicate{27}{abc}}
bye
The second code is inspired by second code presented here by @Joseph where each decimal digit is processed individually. The code (in the accepted answer) uses nested csname
s. I do the same without nested csname
s and the code is more compact. Of course, it works at expand processor level without any need of eTeX primitives:
defreplicate#1{expandafterrepAnumber#1;;}
defrepA#1#2;#3;{ifx;#2;repB#1#3fi repA#2;#1#3;}
defrepB#1fi#2;#3;{firepC{#1}}
defrepC#1#2{repD{#2}#1;}
defrepD#1#2{ifx#2;else repE{#1}#2fi}
defrepE#1#2fi{fi repF#2{#1}repD{repF{10}{#1}}}
defrepF#1#2{ifcase#1 or#2or#2#2or#2#2#2or#2#2#2#2or#2#2#2#2#2or
#2#2#2#2#2#2or#2#2#2#2#2#2#2or#2#2#2#2#2#2#2#2or
#2#2#2#2#2#2#2#2#2or#2#2#2#2#2#2#2#2#2#2fi}
message{replicate{27}{abc}}
bye
edited Mar 21 '16 at 10:06
answered Mar 21 '16 at 9:57
wipetwipet
35.3k4983
35.3k4983
My comment about eTeX was probably misleading: I've removed it (you need eTeX if you want to accept integer expressions for the number of repeats, not for the core idea of making copies).
– Joseph Wright♦
Mar 21 '16 at 10:20
nice but it should be pointed out this doesn't expand fully underromannumeral-`0
.
– user4686
Mar 22 '16 at 22:24
add a comment |
My comment about eTeX was probably misleading: I've removed it (you need eTeX if you want to accept integer expressions for the number of repeats, not for the core idea of making copies).
– Joseph Wright♦
Mar 21 '16 at 10:20
nice but it should be pointed out this doesn't expand fully underromannumeral-`0
.
– user4686
Mar 22 '16 at 22:24
My comment about eTeX was probably misleading: I've removed it (you need eTeX if you want to accept integer expressions for the number of repeats, not for the core idea of making copies).
– Joseph Wright♦
Mar 21 '16 at 10:20
My comment about eTeX was probably misleading: I've removed it (you need eTeX if you want to accept integer expressions for the number of repeats, not for the core idea of making copies).
– Joseph Wright♦
Mar 21 '16 at 10:20
nice but it should be pointed out this doesn't expand fully under
romannumeral-`0
.– user4686
Mar 22 '16 at 22:24
nice but it should be pointed out this doesn't expand fully under
romannumeral-`0
.– user4686
Mar 22 '16 at 22:24
add a comment |
Here is an example with loop and newcommand:
documentclass{article}
newcounter{z}
newcommandy[2]{
loop ifnumvalue{z} < #1
#2%
stepcounter{z}%
repeat
}
begin{document}
y{10}{Hello}
end{document}
The request is to repeat a command
– Andrew Swann
Mar 20 '16 at 15:11
Only the simplest commands - e.g. if the new command defines other commands the grouping is not equivalent.
– Andrew Swann
Mar 20 '16 at 15:23
Isn't this the same as the first suggestion in @morbusg's answer?
– clemens
Mar 20 '16 at 15:27
add a comment |
Here is an example with loop and newcommand:
documentclass{article}
newcounter{z}
newcommandy[2]{
loop ifnumvalue{z} < #1
#2%
stepcounter{z}%
repeat
}
begin{document}
y{10}{Hello}
end{document}
The request is to repeat a command
– Andrew Swann
Mar 20 '16 at 15:11
Only the simplest commands - e.g. if the new command defines other commands the grouping is not equivalent.
– Andrew Swann
Mar 20 '16 at 15:23
Isn't this the same as the first suggestion in @morbusg's answer?
– clemens
Mar 20 '16 at 15:27
add a comment |
Here is an example with loop and newcommand:
documentclass{article}
newcounter{z}
newcommandy[2]{
loop ifnumvalue{z} < #1
#2%
stepcounter{z}%
repeat
}
begin{document}
y{10}{Hello}
end{document}
Here is an example with loop and newcommand:
documentclass{article}
newcounter{z}
newcommandy[2]{
loop ifnumvalue{z} < #1
#2%
stepcounter{z}%
repeat
}
begin{document}
y{10}{Hello}
end{document}
edited Mar 21 '16 at 3:39
answered Mar 20 '16 at 15:04
Steven PennySteven Penny
1
1
The request is to repeat a command
– Andrew Swann
Mar 20 '16 at 15:11
Only the simplest commands - e.g. if the new command defines other commands the grouping is not equivalent.
– Andrew Swann
Mar 20 '16 at 15:23
Isn't this the same as the first suggestion in @morbusg's answer?
– clemens
Mar 20 '16 at 15:27
add a comment |
The request is to repeat a command
– Andrew Swann
Mar 20 '16 at 15:11
Only the simplest commands - e.g. if the new command defines other commands the grouping is not equivalent.
– Andrew Swann
Mar 20 '16 at 15:23
Isn't this the same as the first suggestion in @morbusg's answer?
– clemens
Mar 20 '16 at 15:27
The request is to repeat a command
– Andrew Swann
Mar 20 '16 at 15:11
The request is to repeat a command
– Andrew Swann
Mar 20 '16 at 15:11
Only the simplest commands - e.g. if the new command defines other commands the grouping is not equivalent.
– Andrew Swann
Mar 20 '16 at 15:23
Only the simplest commands - e.g. if the new command defines other commands the grouping is not equivalent.
– Andrew Swann
Mar 20 '16 at 15:23
Isn't this the same as the first suggestion in @morbusg's answer?
– clemens
Mar 20 '16 at 15:27
Isn't this the same as the first suggestion in @morbusg's answer?
– clemens
Mar 20 '16 at 15:27
add a comment |
I tried an alternative to the clever csname
governed expansion from Joseph's answer borrowed from expl3 code.
eTeX is used only to allow input to be an expression: else replace thenumexpr
at the start by number
.
This is less efficient than the David Kastrup + LaTeX team code, although perhaps it becomes about the same when the number of replications is in the thousands (not much tested).
The initial version of this answer had more complicated code which was at about the same level of efficiency. There was an unfortunate chardefz@=0
in that code, which is very wrong and I don't know why it was there.
This answer handles more efficiently than Joseph's the case of a negative asked for number of replication.
It could be easily reworked into a macro (working only in a edef
) leaving tokens behind it rather than in front of it while expanding.
catcode`@ 11
defJFsignfork #10-#2#3krof {#2}
%chardefz@ 0 % NO! z@ is a dimen in TeX/LaTeX
defJFrep #1{romannumeralexpandafterJFrep@athenumexpr #1;3456789XY!}%
defJFrep@a #1{JFsignfork
#1-JFrep@nil
0#1JFrep@neg
0-JFrep@b
krof #1%
}%
longdefJFrep@nil #1!#2{z@}
longdefJFrep@neg #1!#2{z@NegativeReplication}
% TeX numbers have at most 10 digits
defJFrep@b #1#2#3#4#5#6#7#8#9{JFrep@c {.#9.#8.#7.#6.#5.#4.#3.#2;#1}}
defJFrep@c #1#2#3#4!{JFrep@d .#3.#2#1!}
defJFrep@d #1;#2#3{csname JFrep@f#2#3endcsname}
longexpandafterdefcsname JFrep@f.0endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}}%
longexpandafterdefcsname JFrep@f.1endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4}%
longexpandafterdefcsname JFrep@f.2endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4}%
longexpandafterdefcsname JFrep@f.3endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4}%
longexpandafterdefcsname JFrep@f.4endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4}%
longexpandafterdefcsname JFrep@f.5endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.6endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.7endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.8endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.9endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f;1endcsname!#1{z@#1}%
longexpandafterdefcsname JFrep@f;2endcsname!#1{z@#1#1}%
longexpandafterdefcsname JFrep@f;3endcsname!#1{z@#1#1#1}%
longexpandafterdefcsname JFrep@f;4endcsname!#1{z@#1#1#1#1}%
longexpandafterdefcsname JFrep@f;5endcsname!#1{z@#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;6endcsname!#1{z@#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;7endcsname!#1{z@#1#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;8endcsname!#1{z@#1#1#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;9endcsname!#1{z@#1#1#1#1#1#1#1#1#1}%
catcode`@ 12
edeftest{JFrep{123}{abc}}
showtest
bye
There is now anxintreplicate
in xint but it is a clone of the expl3's code with very minor changes, it is not the code of this answer...
– user4686
Apr 29 '18 at 20:26
add a comment |
I tried an alternative to the clever csname
governed expansion from Joseph's answer borrowed from expl3 code.
eTeX is used only to allow input to be an expression: else replace thenumexpr
at the start by number
.
This is less efficient than the David Kastrup + LaTeX team code, although perhaps it becomes about the same when the number of replications is in the thousands (not much tested).
The initial version of this answer had more complicated code which was at about the same level of efficiency. There was an unfortunate chardefz@=0
in that code, which is very wrong and I don't know why it was there.
This answer handles more efficiently than Joseph's the case of a negative asked for number of replication.
It could be easily reworked into a macro (working only in a edef
) leaving tokens behind it rather than in front of it while expanding.
catcode`@ 11
defJFsignfork #10-#2#3krof {#2}
%chardefz@ 0 % NO! z@ is a dimen in TeX/LaTeX
defJFrep #1{romannumeralexpandafterJFrep@athenumexpr #1;3456789XY!}%
defJFrep@a #1{JFsignfork
#1-JFrep@nil
0#1JFrep@neg
0-JFrep@b
krof #1%
}%
longdefJFrep@nil #1!#2{z@}
longdefJFrep@neg #1!#2{z@NegativeReplication}
% TeX numbers have at most 10 digits
defJFrep@b #1#2#3#4#5#6#7#8#9{JFrep@c {.#9.#8.#7.#6.#5.#4.#3.#2;#1}}
defJFrep@c #1#2#3#4!{JFrep@d .#3.#2#1!}
defJFrep@d #1;#2#3{csname JFrep@f#2#3endcsname}
longexpandafterdefcsname JFrep@f.0endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}}%
longexpandafterdefcsname JFrep@f.1endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4}%
longexpandafterdefcsname JFrep@f.2endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4}%
longexpandafterdefcsname JFrep@f.3endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4}%
longexpandafterdefcsname JFrep@f.4endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4}%
longexpandafterdefcsname JFrep@f.5endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.6endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.7endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.8endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.9endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f;1endcsname!#1{z@#1}%
longexpandafterdefcsname JFrep@f;2endcsname!#1{z@#1#1}%
longexpandafterdefcsname JFrep@f;3endcsname!#1{z@#1#1#1}%
longexpandafterdefcsname JFrep@f;4endcsname!#1{z@#1#1#1#1}%
longexpandafterdefcsname JFrep@f;5endcsname!#1{z@#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;6endcsname!#1{z@#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;7endcsname!#1{z@#1#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;8endcsname!#1{z@#1#1#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;9endcsname!#1{z@#1#1#1#1#1#1#1#1#1}%
catcode`@ 12
edeftest{JFrep{123}{abc}}
showtest
bye
There is now anxintreplicate
in xint but it is a clone of the expl3's code with very minor changes, it is not the code of this answer...
– user4686
Apr 29 '18 at 20:26
add a comment |
I tried an alternative to the clever csname
governed expansion from Joseph's answer borrowed from expl3 code.
eTeX is used only to allow input to be an expression: else replace thenumexpr
at the start by number
.
This is less efficient than the David Kastrup + LaTeX team code, although perhaps it becomes about the same when the number of replications is in the thousands (not much tested).
The initial version of this answer had more complicated code which was at about the same level of efficiency. There was an unfortunate chardefz@=0
in that code, which is very wrong and I don't know why it was there.
This answer handles more efficiently than Joseph's the case of a negative asked for number of replication.
It could be easily reworked into a macro (working only in a edef
) leaving tokens behind it rather than in front of it while expanding.
catcode`@ 11
defJFsignfork #10-#2#3krof {#2}
%chardefz@ 0 % NO! z@ is a dimen in TeX/LaTeX
defJFrep #1{romannumeralexpandafterJFrep@athenumexpr #1;3456789XY!}%
defJFrep@a #1{JFsignfork
#1-JFrep@nil
0#1JFrep@neg
0-JFrep@b
krof #1%
}%
longdefJFrep@nil #1!#2{z@}
longdefJFrep@neg #1!#2{z@NegativeReplication}
% TeX numbers have at most 10 digits
defJFrep@b #1#2#3#4#5#6#7#8#9{JFrep@c {.#9.#8.#7.#6.#5.#4.#3.#2;#1}}
defJFrep@c #1#2#3#4!{JFrep@d .#3.#2#1!}
defJFrep@d #1;#2#3{csname JFrep@f#2#3endcsname}
longexpandafterdefcsname JFrep@f.0endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}}%
longexpandafterdefcsname JFrep@f.1endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4}%
longexpandafterdefcsname JFrep@f.2endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4}%
longexpandafterdefcsname JFrep@f.3endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4}%
longexpandafterdefcsname JFrep@f.4endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4}%
longexpandafterdefcsname JFrep@f.5endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.6endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.7endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.8endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.9endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f;1endcsname!#1{z@#1}%
longexpandafterdefcsname JFrep@f;2endcsname!#1{z@#1#1}%
longexpandafterdefcsname JFrep@f;3endcsname!#1{z@#1#1#1}%
longexpandafterdefcsname JFrep@f;4endcsname!#1{z@#1#1#1#1}%
longexpandafterdefcsname JFrep@f;5endcsname!#1{z@#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;6endcsname!#1{z@#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;7endcsname!#1{z@#1#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;8endcsname!#1{z@#1#1#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;9endcsname!#1{z@#1#1#1#1#1#1#1#1#1}%
catcode`@ 12
edeftest{JFrep{123}{abc}}
showtest
bye
I tried an alternative to the clever csname
governed expansion from Joseph's answer borrowed from expl3 code.
eTeX is used only to allow input to be an expression: else replace thenumexpr
at the start by number
.
This is less efficient than the David Kastrup + LaTeX team code, although perhaps it becomes about the same when the number of replications is in the thousands (not much tested).
The initial version of this answer had more complicated code which was at about the same level of efficiency. There was an unfortunate chardefz@=0
in that code, which is very wrong and I don't know why it was there.
This answer handles more efficiently than Joseph's the case of a negative asked for number of replication.
It could be easily reworked into a macro (working only in a edef
) leaving tokens behind it rather than in front of it while expanding.
catcode`@ 11
defJFsignfork #10-#2#3krof {#2}
%chardefz@ 0 % NO! z@ is a dimen in TeX/LaTeX
defJFrep #1{romannumeralexpandafterJFrep@athenumexpr #1;3456789XY!}%
defJFrep@a #1{JFsignfork
#1-JFrep@nil
0#1JFrep@neg
0-JFrep@b
krof #1%
}%
longdefJFrep@nil #1!#2{z@}
longdefJFrep@neg #1!#2{z@NegativeReplication}
% TeX numbers have at most 10 digits
defJFrep@b #1#2#3#4#5#6#7#8#9{JFrep@c {.#9.#8.#7.#6.#5.#4.#3.#2;#1}}
defJFrep@c #1#2#3#4!{JFrep@d .#3.#2#1!}
defJFrep@d #1;#2#3{csname JFrep@f#2#3endcsname}
longexpandafterdefcsname JFrep@f.0endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}}%
longexpandafterdefcsname JFrep@f.1endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4}%
longexpandafterdefcsname JFrep@f.2endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4}%
longexpandafterdefcsname JFrep@f.3endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4}%
longexpandafterdefcsname JFrep@f.4endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4}%
longexpandafterdefcsname JFrep@f.5endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.6endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.7endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.8endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f.9endcsname #1#2#3!#4%
{csname JFrep@f#1#2endcsname#3!{#4#4#4#4#4#4#4#4#4#4}#4#4#4#4#4#4#4#4#4}%
longexpandafterdefcsname JFrep@f;1endcsname!#1{z@#1}%
longexpandafterdefcsname JFrep@f;2endcsname!#1{z@#1#1}%
longexpandafterdefcsname JFrep@f;3endcsname!#1{z@#1#1#1}%
longexpandafterdefcsname JFrep@f;4endcsname!#1{z@#1#1#1#1}%
longexpandafterdefcsname JFrep@f;5endcsname!#1{z@#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;6endcsname!#1{z@#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;7endcsname!#1{z@#1#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;8endcsname!#1{z@#1#1#1#1#1#1#1#1}%
longexpandafterdefcsname JFrep@f;9endcsname!#1{z@#1#1#1#1#1#1#1#1#1}%
catcode`@ 12
edeftest{JFrep{123}{abc}}
showtest
bye
edited Apr 13 '17 at 12:34
Community♦
1
1
answered Mar 23 '16 at 11:47
user4686
There is now anxintreplicate
in xint but it is a clone of the expl3's code with very minor changes, it is not the code of this answer...
– user4686
Apr 29 '18 at 20:26
add a comment |
There is now anxintreplicate
in xint but it is a clone of the expl3's code with very minor changes, it is not the code of this answer...
– user4686
Apr 29 '18 at 20:26
There is now an
xintreplicate
in xint but it is a clone of the expl3's code with very minor changes, it is not the code of this answer...– user4686
Apr 29 '18 at 20:26
There is now an
xintreplicate
in xint but it is a clone of the expl3's code with very minor changes, it is not the code of this answer...– user4686
Apr 29 '18 at 20:26
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f16189%2frepeat-command-n-times%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Note that
repeat
is already defined by LaTeX as end-macro forloop
.– Martin Scharrer♦
Apr 19 '11 at 19:34