Difference between revisions of "System Macros/Loops and Recursion"
m (Text replacement - "</cmd>" to "}}") |
|||
(9 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
− | < '''Prev:''' [[System Macros/Branches and Decisions| | + | < '''Prev:''' [[System Macros/Branches and Decisions|Branches & Decisions]] | '''Top:''' [[System Macros]] | '''Next:''' [[System Macros/Action Processing|Action Processing]] > |
− | + | TeX does not offer us powerful for-loop mechanisms. On | |
− | === | + | the other hand its recursion engine is quite unique. We |
+ | therefore identify the for-looping macros by this method. | ||
+ | The most simple alternative is the one that only needs a | ||
+ | number. | ||
+ | |||
+ | === {{cmd|dorecurse}} === | ||
<texcode> | <texcode> | ||
\dorecurse {n} {whatever we want} | \dorecurse {n} {whatever we want} | ||
Line 36: | Line 41: | ||
− | === | + | === {{cmd|dostepwiserecurse}} === |
The simple command <code>\dorecurse</code> is | The simple command <code>\dorecurse</code> is | ||
a special case of the more general: | a special case of the more general: | ||
Line 53: | Line 58: | ||
</texcode> | </texcode> | ||
− | === | + | === {{cmd|doloop}} {{cmd|exitloop}} === |
Sometimes loops are not determined by counters, but by | Sometimes loops are not determined by counters, but by | ||
(a combinations of) conditions. We therefore implement a | (a combinations of) conditions. We therefore implement a | ||
straightforward loop, which can only be left when we | straightforward loop, which can only be left when we | ||
− | + | explicitly exit it. Nesting is supported. First we present | |
a more extensive alternative. | a more extensive alternative. | ||
Line 66: | Line 71: | ||
</texcode> | </texcode> | ||
− | When needed, one can call for <code>\ | + | When needed, one can call for <code>\recurselevel</code> and |
− | <code>\ | + | <code>\recursedepth</code>. |
The loop is executed at least once, so beware of situations | The loop is executed at least once, so beware of situations | ||
Line 87: | Line 92: | ||
for conditional errors. | for conditional errors. | ||
− | < '''Prev:''' [[System Macros/Branches and Decisions| | + | === Recursion and expansion === |
+ | |||
+ | Using recursion to build tables requires some particular attention: | ||
+ | |||
+ | <context source="yes"> | ||
+ | \bTABLE | ||
+ | \bTR | ||
+ | \dorecurse{8}{\expanded{\bTD\recurselevel\eTD}} | ||
+ | \eTR | ||
+ | \eTABLE | ||
+ | </context> | ||
+ | |||
+ | Multi-dimensional tables offer another illustration: | ||
+ | |||
+ | <context source="yes"> | ||
+ | \bTABLE | ||
+ | \dorecurse{8}{ | ||
+ | \bTR | ||
+ | \dorecurse{5}{\bTD #1,##1 \eTD} | ||
+ | \eTR | ||
+ | } | ||
+ | \eTABLE | ||
+ | </context> | ||
+ | |||
+ | Alternatively, (mkiv only?) | ||
+ | |||
+ | <context source="yes"> | ||
+ | \bTABLE | ||
+ | \dorecurse{8}{\bTR | ||
+ | \dorecurse{5}{\bTD \currentTABLErow,\currentTABLEcolumn \eTD} | ||
+ | \eTR} | ||
+ | \eTABLE | ||
+ | </context> | ||
+ | |||
+ | For further discussion on loops and expansion, see [[System_Macros/Expansion_Control|Expansion control]] as well as this [http://randomdeterminism.wordpress.com/2009/03/05/tex-programming-the-past-the-present-and-the-future/ blog post]. | ||
+ | |||
+ | < '''Prev:''' [[System Macros/Branches and Decisions|Branches & Decisions]] | '''Top:''' [[System Macros]] | '''Next:''' [[System Macros/Action Processing|Action Processing]] > | ||
− | [[Category: | + | [[Category:Programming and Databases]] |
− | [[Category: | + | [[Category:Tools]] |
Revision as of 13:27, 9 August 2020
< Prev: Branches & Decisions | Top: System Macros | Next: Action Processing >
TeX does not offer us powerful for-loop mechanisms. On the other hand its recursion engine is quite unique. We therefore identify the for-looping macros by this method. The most simple alternative is the one that only needs a number.
\dorecurse
\dorecurse {n} {whatever we want}
This macro can be nested without problems and therefore be
used in situations where Plain TeX's \loop
macro
ungracefully fails. The current value of the counter is
available in \recurselevel
, before as well as after
the whatever we want
stuff.
\dorecurse % inner loop {10} {\recurselevel: % outer value \dorecurse % inner loop {\recurselevel} % outer value {\recurselevel} % inner value \dorecurse % inner loop {\recurselevel} % outer value {\recurselevel} % inner value \endgraf}
In this example the first, second and fourth
\recurselevel
concern the outer loop, while the third
and fifth one concern the inner loop. The depth of the
nesting is available for inspection in \recursedepth
.
Both \recurselevel
and \recursedepth
are
macros. The real conters are hidden from the user because
we don't want any interference.
\dostepwiserecurse
The simple command \dorecurse
is
a special case of the more general:
\dostepwiserecurse {from} {to} {step} {action}
This commands accepts positive and negative steps. Illegal values are handled as good as possible and the macro accepts numbers and counters.
\dostepwiserecurse {1} {10} {2} {...} \dostepwiserecurse {10} {1} {-2} {...}
\doloop \exitloop
Sometimes loops are not determined by counters, but by (a combinations of) conditions. We therefore implement a straightforward loop, which can only be left when we explicitly exit it. Nesting is supported. First we present a more extensive alternative.
\doloop {Some kind of typesetting punishment \par \ifnum\pageno>100 \exitloop \fi}
When needed, one can call for \recurselevel
and
\recursedepth
.
The loop is executed at least once, so beware of situations like:
\doloop {\exitloop some commands}
It's just a matter of putting the text into the \if
statement that should be there anyway, like in:
\doloop {\ifwhatever \exitloop \else some commands\fi}
You can also quit a loop immediately, by using
\exitloopnow
instead. Beware, this is more sensitive
for conditional errors.
Recursion and expansion
Using recursion to build tables requires some particular attention:
\bTABLE \bTR \dorecurse{8}{\expanded{\bTD\recurselevel\eTD}} \eTR \eTABLE
Multi-dimensional tables offer another illustration:
\bTABLE \dorecurse{8}{ \bTR \dorecurse{5}{\bTD #1,##1 \eTD} \eTR } \eTABLE
Alternatively, (mkiv only?)
\bTABLE \dorecurse{8}{\bTR \dorecurse{5}{\bTD \currentTABLErow,\currentTABLEcolumn \eTD} \eTR} \eTABLE
For further discussion on loops and expansion, see Expansion control as well as this blog post.
< Prev: Branches & Decisions | Top: System Macros | Next: Action Processing >