# Different behaviour of Map and Inner in replace rules

Why does

x[{1, 2}] /. {x[l_] -> Map[func, l]}


{1, 2}

not behave as expected, while for example

x[{1, 2}] /. {x[l_] -> Inner[func, l, l]}


func[1, 1] + func[2, 2]

gives the expected result?

I know that I can fix the first example by using :> instead of ->, but I don't understand why.

Is there another way to make the example with Map work as in the case of Inner?

• Welcome to Mathematica.SE! I suggest that: 1) You take the introductory Tour now! 2) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! 3) As you receive help, try to give it too, by answering questions in your area of expertise. Commented Apr 15, 2015 at 12:27

Map[func,l]


will evaluate to verbatim l while building up the replacement rules. When the replacement is then done, the replacement rule used is x[l_] -> l.

My guess why Map[func, l] evaluates the way it does is that Map works by "inserting" func into it's second argument at the default mapping level, 1. As there is no such level because l is an atomic symbol, the result is just l.

In the second case

Inner[func, l, l]


Inner does not evaluate to something different, so it survives until the l is replaced with the value from the left side of the rule.

Using :> is really the right way to go when there are patterns on the left hand side.

• Ok, but why does Map[func,l] evaluate to l in this case? Commented Apr 15, 2015 at 12:31
• @Severin see edit. Commented Apr 15, 2015 at 12:51

Malte Lenz is correct; there are no level one expressions in l therefore the Map operation appears inert. (The default levelspec of Map is {1}.) Observe that if a levelspec of {0} is used the func is applied:

Map[func, l, {0}]

func[l]


If you are asking why conceptually Map works this way I can only say that in my experience the existing behavior has been convenient and powerful many times. If for whatever reason you want a Map analogue that does not evaluate until the operation is non-inert I propose:

delayMap[f_, expr_, lev_: {1}, opt : OptionsPattern[Map]] /;
{} =!= Position[expr, _, lev, 1, Heads -> OptionValue[Map, {opt}, Heads]] :=
Map[f, expr, lev, opt]


Now:

test = delayMap2[func, l]

delayMap[func, l]

l = {1, 2, 3};

test

{func[1], func[2], func[3]}


The somewhat baroque definition is primarily to handle the Heads option of Map.