Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Consider the following function definition:

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

Two questions about it:

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}]?

share|improve this question
4  
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. –  Leonid Shifrin Mar 1 '12 at 9:32

2 Answers 2

up vote 8 down vote accepted

The key here is learning about evaluation control. Please see the tutorials linked from this page.


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?

share|improve this answer
    
Pre :> k++ is the trick for the second part. I just missed it. –  Mohsen Mar 1 '12 at 9:14
    
@Mohsen Read about evaluation control in the link I included at the top. –  Szabolcs 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. –  Mohsen Mar 1 '12 at 9:22
5  
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. –  Leonid Shifrin 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. –  Szabolcs 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]] - 1) + #2[[2]]] &, data, {2}]

(same output)

share|improve this answer
2  
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. –  Mohsen Mar 1 '12 at 22:09

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.