I would like to use \foreach inside an \edef, for example to define a set of random points as follows:

  \foreach \x in {0,.1,...,1}
           {\pgfmathparse{rand} (\x,\pgfmathresult)}}

Unfortunately, the above code causes an error about Undefined control sequence \pgffor@remember@once@code.

My questions are why this doesn't work, and what the simplest workaround is for saving the result of a \foreach loop.

  • I think we've got a lot questions on the \foreach expansion trap
    – user31729
    Commented Oct 6, 2015 at 20:24
  • 1
    @ChristianHupfer When I search for "foreach expansion trap," I get no results on stackexchange, so how do I find these? Commented Oct 6, 2015 at 20:26
  • Do you really need \edef? Commented Oct 6, 2015 at 20:26
  • @GonzaloMedina It's absolutely necessary. Otherwise, I get new random points each time, which doesn't work very well in, say, overlay slides. Commented Oct 6, 2015 at 20:27
  • @user3188445 You can set a seed: \pgfmathsetseed{1} Commented Oct 6, 2015 at 20:30

2 Answers 2


The other answer provides a solution which works but has the downside of using global definitions, which should be avoided unless really necessary. pgf comes with the /.list key handler which allows one to avoid the global definitions.

\begin{tikzpicture}[add point/.code={\pgfmathparse{rand}%
    \def\mypoints{} % initialize
    \tikzset{add point/.list={0,0.2,...,5}}% loop without global definitions
    \draw plot coordinates {\mypoints};

You have to do the cycle outside the \edef:

\gdef\mypoints{} % initialize
\foreach\x in {0,0.1,...,1} {%

so at each cycle you append the new point.

With the code above we might get something like


(line breaks for clarity). Well, not really what we expected.

We can avoid this and also global declarations.



 {% #1 = start, #2 = step, #3 = end, #4 = template
  \fp_step_inline:nnnn { #1 } { #2 } { #3 } { #4 }

  \tl_clear_new:c { l_egreg_list_#1_tl }
  \IfBooleanTF{#1}{\tl_put_right:cx}{\tl_put_right:cn} { l_egreg_list_#2_tl } { #3 }
  \tl_use:c { l_egreg_list_#1_tl }

\clearlist{points} % initialize
  \addtolist*{points}{(#1,\fpeval{round(2*rand()-1,4)}) }




Since rand() only returns numbers between 0 and 1, but the pgfmath function rand returns numbers from −1 to 1, I use 2*rand()-1.

A possible output is

enter image description here

The trailing space is just for typesetting purposes. In the fourth argument of \fpforeach, #1 stands for the current value in the loop.

The \addtolist command simply adds, but with * it also does full expansion.

Note that the x-coordinates are indeed from 0 to 1, because l3fp uses floating point decimal numbers (not fixed precision binary converted into decimal like pgfmath).

  • That answers half of my question, thanks. But can you explain why it doesn't work? Commented Oct 6, 2015 at 20:41
  • @user3188445 No assignments are performed in an \edef, just macro expansion is done. There are several topics on the site that deal with the problem.
    – egreg
    Commented Oct 6, 2015 at 20:43
  • @user3188445 Try \edef\mypoints{\pgfmathparse{rand}}. Not everything is expandable.
    – percusse
    Commented Oct 6, 2015 at 21:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .