[Tex/LaTex] Use a loop to generate a list for another (foreach) loop

loopsprogrammingtikz-pgf

Is it possible to use a loop to generate a list for a foreach loop? More specifically I want the following:

Consider the following answer to a question I asked some time ago: https://tex.stackexchange.com/a/38793/4011

It worked very well except if I define \alist as follows:

\def\alist{
    \foreach \i in {1,2,3}{
      \i/1,
      }4/1
    }

I get the following error:

ERROR: Undefined control sequence.

--- TeX said ---
\foreach ...reach \let \pgffor@assign@before@code 
                                                  =\pgfutil@empty \let \pgff...
l.38   \rectDiv{7}{5}{(1,1)}{(4,3)}{\alist}

Is there any way to fix this?

Edit:

Full example:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
  \def\rectDiv#1#2#3#4#5{%#columns, #rows, rectangle start, rectangle end, list of elements to fill
    \begin{tikzpicture}
      \draw #3 rectangle #4;
      \path #3;
      \pgfgetlastxy{\firstx}{\firsty}
      \path #4;
      \pgfgetlastxy{\secondx}{\secondy}
      \pgfmathsetlengthmacro{\xdiff}{\secondx-\firstx}
      \pgfmathsetlengthmacro{\ydiff}{\secondy-\firsty}
      \pgfmathsetlengthmacro{\myxstep}{\xdiff/#1}
      \pgfmathsetlengthmacro{\myystep}{\ydiff/#2}
      \foreach \x in {1,...,#1}{
        \draw ($#3 +\x*(\myxstep,0)$) -- ($#3 +(0,\ydiff) +\x*(\myxstep,0)$);
      }
      \foreach \y in {1,...,#2}{
        \draw ($#3 +\y*(0,\myystep)$) -- ($#3 +(\xdiff,0) +\y*(0,\myystep)$);
      }
      \edef\temp{\noexpand\foreach \noexpand\i/\noexpand\j in {#5}}
      \temp{
        \path[fill=blue!20,draw] ($#3 + (\i*\myxstep,\j*\myystep)$) rectangle ($#3 + (\i*\myxstep,\j*\myystep) + (\myxstep,\myystep)$);
      }
    \end{tikzpicture}
  }
\begin{document}
  \rectDiv{7}{5}{(1,1)}{(4,3)}{0/0,1/1,2/0,5/3}

  \def\list{1/0}
  \rectDiv{7}{5}{(1,1)}{(4,3)}{\list}

  \rectDiv{7}{5}{(1,1)}{(4,3)}{\list,2/0,5/3}

  \def\alist{
    \foreach \i in {1,2,3}{
      \i/1,
      }4/1
    }

   \alist

   \rectDiv{7}{5}{(1,1)}{(4,3)}{\alist}  %this doesn't  work

\end{document}

Best Answer

Your problem is that you wrote

\edef\temp{\noexpand\foreach \noexpand\i/\noexpand\j in {#5}}

% Here is what #5 is in \temp:
\def\alist{
\foreach \i in {1,2,3}{
  \i/1,
  }4/1
}

which requires that the stuff in the braces be "fully expandable". Alas, \foreach is not expandable, and it is part of \alist. So when \temp is defined, it expands "as much as possible" and hits some non-expandable part of the code of \foreach, which in this case is \let \pgffor@assign@before@code = ...; \let is an assignment, and not expandable, so is not changed by \edef. Thus, the assignment is not actually performed, and \edef goes on to try to interpret the following control sequence \pgffor@assign@before@code directly. Not surprisingly, it is not defined, since it was the \let that is supposed to define it, so you get an error.

To do this, you have to create a macro that contains the output of \alist. For example,

\gdef\alist{}
\foreach \i in {1,2,3} {
 \xdef\alist{\alist \i/1,}
}
\xdef\alist{\alist 4/1}

Then you can use \alist directly instead of \temp. (I have used global assignments for \alist because \foreach executes its contents in a group.)