# Defining a ForEach function

Consider the following function definition:

ForEach[iterators__] := Table[#, iterators] &;

I. It works perfectly if you call it like ForEach[{m,3},{n,3}]@{m,n} and outputs:

$$\left( \begin{array}{ccc} \{1,1\} & \{1,2\} & \{1,3\} \\ \{2,1\} & \{2,2\} & \{2,3\} \\ \{3,1\} & \{3,2\} & \{3,3\} \end{array} \right)$$

However, the result of ForEach[{m, 3}, {n, 3}]@ToString[m n] is:

$$\left( \begin{array}{ccc} \text{m n} & \text{m n} & \text{m n} \\ \text{m n} & \text{m n} & \text{m n} \\ \text{m n} & \text{m n} & \text{m n} \end{array} \right)$$

Why it doesn't treat m and n as known variables?

II. How can I pass a piece of code to the function to be run before each iteration? For instance, I want to call the function with an option like k=0; ForEach[{m, 3}, {n, 3},Pre->k++]@{k,m,n} which is the same as k = 0; Table[k++; {k, m, n}, {m, 3}, {n, 3}]?

• This question was asked in variations on SO before: e.g here, here, and here. You may find those discussions interesting, if not exactly addressing your particular question. Mar 1 '12 at 9:32

Use TracePrint to see how it is evaluated and you'll understand.

In

ForEach[{m, 3}, {n, 3}]@ToString[m n]


ToString[m n] is evaluated to "m n" before ForEach even sees it. Also, if m or n have values, this'll break. Set a HoldAll attribute in the function:

ClearAll[ForEach]
SetAttributes[ForEach, HoldAll]
ForEach[iterators__] := Function[arg, Table[arg, iterators], HoldAll]


For the second part simply requires learning about option handling:

ClearAll[ForEach]
SetAttributes[ForEach, HoldAll]
Options[ForEach] = {Pre -> Null}
ForEach[iterators__, OptionsPattern[]] :=
Function[arg, Table[OptionValue[Pre]; arg, iterators], HoldAll]

k = 0
ForEach[{n, 3}, {m, 3}, Pre :> k++][ToString@{m, n, k}]


Making this is good as a learning exercise, but I find this construct problematic and fragile. If you want to use this to solve actual problems, other approaches are better. Why don't you describe the problem that you want to solve?

• Pre :> k++ is the trick for the second part. I just missed it. Mar 1 '12 at 9:14
• @Mohsen Read about evaluation control in the link I included at the top. Mar 1 '12 at 9:21
• The problem is quite technical and not very "Mathematical". I have already solved the problem but I am looking for ways to make the code more readable. The problem is that I have too many/long nested calls which makes the code somewhat hard to read, specially for non-programmers. I want to write some function to make a DSL out of Mathematica. Then, I want to use the DSL to make my code more human understandable. Mar 1 '12 at 9:22
• I probably should not be saying this, but I find the doc tutorials on evaluation rather useless for beginners. In my opinion, evaluation should be discussed in a coherent manner, explaining the role of various constructs by showing how they affect the evaluation sequence, rather than just listing some of their properties. Otherwise, you just create some magic spells, and multiply entities, precisely opposite to the Occam's razor principle. Within the currently existing literature, the best account on evaluation is IMO chapter 7 of David Wagner's book, which I can't recommend highly enough. Mar 1 '12 at 12:00
• @Leonid Feel free to edit my answer with links or add a completely new one. I'll be glad to recommend it. I am trying to reduce my participation these days (with difficulty), it's hurting my productivity--so I can't improve on the answer now. Mar 1 '12 at 12:07

Maybe I misunderstood your question, but what about Map/MapIndexed, which are pretty much the functional equivalents to ForEach constructs?

data = Table[{m, n}, {m, 3}, {n, 3}]
k = 0
Map[Prepend[#, ++k] &, data, {2}]

{{{1, 1, 1}, {2, 1, 2}, {3, 1, 3}}, {{4, 2, 1}, {5, 2, 2}, {6, 2, 3}}, {{7, 3, 1}, {8, 3, 2}, {9, 3, 3}}}


Or alternatively, using no state variable,

MapIndexed[Prepend[#, 3 (#2[] - 1) + #2[]] &, data, {2}]


(same output)

• As I described in the comment under Szabolcs's answer, I need the ForEach construct to improve the readability of a piece of code for non-programmers. Otherwise, there are many other ways to get the job done. Mar 1 '12 at 22:09