5

If I use the construct

f[#] & /@ f[#] & /@ f[#] & /@ {a, b, c}

my function works, but if I use

Nest[f, #, 3] & /@ {a, b, c}

it doesn't. What is the difference, and how can I code the top example without copying and pasting?

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
martin
  • 8,678
  • 4
  • 23
  • 70

2 Answers2

5

Analysis

Function is left-associative as converting to StandardForm reveals:

(((f[#1] &) /@ f[#1] &) /@ f[#1] &) /@ {a, b, c}

You can see the result of the rather odd operation with:

f = {#, "x"} &;

f[#] & /@ f[#] & /@ f[#] & /@ {a, b, c}
{{{{a, x}, {x, x}}, {{x, x}, {x, x}}},
 {{{b, x}, {x, x}}, {{x, x}, {x, x}}},
 {{{c, x}, {x, x}}, {{x, x}, {x, x}}}}

(Obviously the structure is specific to the output of f but I hope it serves to illustrate.)

Additionally the order of evaluation is not the same as a Map operation with a levelspec because one entire branch executes first. Compare these results:

i = 0;
f = {#, i++} &;
f[#] & /@ f[#] & /@ f[#] & /@ {a, b, c}
{{{{a, 2}, {1, 3}}, {{0, 5}, {4, 6}}},
 {{{b, 9}, {8, 10}}, {{7, 12}, {11, 13}}},
 {{{c, 16}, {15, 17}}, {{14, 19}, {18, 20}}}}
i = 0;
f = {#, i++} &;
Fold[Map[f, #, {#2}] &, {a, b, c}, Range@3]
{{{{a, 9}, {3, 10}}, {{0, 11}, {4, 12}}},
 {{{b, 13}, {5, 14}}, {{1, 15}, {6, 16}}},
 {{{c, 17}, {7, 18}}, {{2, 19}, {8, 20}}}}

I am attempting to think of a clean way to produce the first output (with arbitrary levels of mapping).

Solution

After a chat session I propose:

mapRepeated[f_, expr_, n_Integer?Positive] :=
  Nest[x \[Function] x /@ f[#] &, f, n - 1] /@ expr

Test:

i = 0;

mapRepeated[{#, i++} &, {a, b, c}, 3]
{{{{a, 2}, {1, 3}}, {{0, 5}, {4, 6}}},
 {{{b, 9}, {8, 10}}, {{7, 12}, {11, 13}}},
 {{{c, 16}, {15, 17}}, {{14, 19}, {18, 20}}}}

Using Mathematica 10 syntax the we can simplify mapRepeated slightly:

mapRepeated[f_, expr_, n_Integer?Positive] :=
  Nest[Map[#]@*f &, f, n - 1] /@ expr
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
0

I am not sure which from of the solutions you are looking at but you can try this:

f = #+1&; 
Composition[Sequence @@ ConstantArray[f, 2]][f[#]] & /@ {a, b, c}
(*{3 + a, 3 + b, 3 + c}*)

how about this:

Nest[Map[f, #,{-1}] &, f[#], 2] & /@ {a, b, c}
Basheer Algohi
  • 19,917
  • 1
  • 31
  • 78