Since I normally use tikz in my documents, I mostly use the \foreach \x in \list loop to repeat things. However, this famously fails in tabular environments and also everywhere where things must be expanded.
Thus I've written a \for macro which works in tabular, but I'd like to know how to do it better. It's not completely expandable and probably also quite inefficient.
This is okay, because most tables don't have thousands of cells, so performance is usually not an issue. It works in tabular environments to generate multiple columns in a single line or - with some additional care - to generate multiple rows:

As mentioned above, there are clearly some issues with this loop, but most of the time it "works for me". Still I'd like to improve it, so these are the points that bug me the most:
- Each iteration's loop body is completely expanded using
\edef. This ensures that the loop counter is expanded to its value during that iteration. However this also requires the user to protect some things using\noexpand, like\pgfmathparseor\\and\hlinein the tables below. Also it would require double protection (triple\noexpandmaybe?) for nested loops. - Obviously it's not completely expandable because it uses
\defand\edef, so it's not possible to use the loop inside, say, another\edefin order to define a macro that has a regular structure. Although of course it's perfectly possible to\defa macro that expands to a loop invocation.
Now, how could these be solved?
- For problem 1 it would be great to have a way to expand only the
loop counter anywhere it's used in the loop body, but leave
everything else alone. This would eliminate all the
\noexpands. - For problem 2 I suspect that it could be possible to sacrifice some functionality, like the flexible loop counters and conditions (e.g.
\repeat{\i}{5}{some code using \i}instead of the C-like syntax).
However I don't really know how to approach these problems. Can anyone give me some pointers in the right direction? Is it at all possible to achieve both, selective expansion and complete expandability?
Finally, here's the code:
\documentclass{article}
\begin{filecontents*}{myforloop.sty}
\usepackage{pgf}
\usepackage{pgffor}
\usepackage{ifthen}
% Example:
% \for (\i = 0; \i < 10; \i = \i + 1) {
% some code using \i
% }
\def\for(#1=#2;#3;#4=#5)#6{%
\def\forloopresult{}% Macro to store the result
\pgfmathtruncatemacro{#1}{#2}% Set initial value of counter
\def\forloopinner{% Recursive loop macro
\pgfmathparse{int(#3)}% Calculate loop condition
\ifthenelse{1=\pgfmathresult\relax}{% if loop condition is true:
\toks@=\expandafter{\forloopresult}% Get tokens from result macro
\edef\forloopresult{\the\toks@#6}% Append expanded code to result
\pgfmathtruncatemacro{#1}{#5}% Set new counter value
\forloopinner% Recurse
}{% else:
\forloopresult% Expand to result
}%
}%
\forloopinner% Start looping
}
\end{filecontents*}
\usepackage{myforloop}
\newcommand\N{5}% Number of loop iterations
\begin{document}
\begin{tabular}{|r|*{\N}{r|}}
\hline
$x$: \for(\x=0; \x<\N; \x=\x+1) {&\x}\\\hline
$e^x$: \for(\x=0; \x<\N; \x=\x+1) {%
& \noexpand\pgfmathparse{exp(\x)}\noexpand\pgfmathresult%
}\\\hline
\end{tabular}
\vspace{1em}
\begin{tabular}{|l|l|}
\hline
$x$ & $e^x$ \\\hline
\for(\x=0; \x<\N; \x=\x+1) {%
\x & \noexpand\pgfmathparse{exp(\x)}\noexpand\pgfmathresult
\noexpand\\\noexpand\hline
}
\end{tabular}
\end{document}

code using #1that you want to repeat, right? On the other hand, Joseph'sexpl3answer seems to pass the code that uses#1as a parameter... somehow. – Fritz Aug 18 '14 at 12:42expl3we have the set up 'pre-created' so it's work having a nice interface (one set of loop functions, just provide a command to 'do stuff'). – Joseph Wright Aug 18 '14 at 12:50\myrepeatis11or more. (because\myrepeatfetches only the first digit) – Mar 11 '15 at 09:57