5
$\begingroup$

This returns errors:

{#[[1]],#[[3]]} & /@ {#[[1]],#[[2]],#[[3]]} & /@ {{"A","B","C"},{1,2,3}}

Part::partd: Part specification A[[1]] is longer than depth of object. >>
...

But when adding parentheses after first /@ (Map) and closing it on the end of expression, as in:

{#[[1]],#[[3]]} & /@ ({#[[1]],#[[2]],#[[3]]} & /@ {{"A","B","C"},{1,2,3}})

everything goes fine and returns expected result: {{"A", "C"}, {1, 3}}

How to explain the behavior of first case? I cannot figure out what cause errors in first case.

$\endgroup$
  • 1
    $\begingroup$ Your question notwithstanding, are you perhaps looking for {{"A", "B", "C"}, {1, 2, 3}}[[All, {1, 3}]]? You might also be interested in Elegant operations on matrix rows and columns. $\endgroup$ – MarcoB Jul 5 '16 at 18:57
  • $\begingroup$ No. I ask, why first case returns errors: "Part specification \!\(\"A\"[[1]]\) is longer than depth of object.", and returns something like generic result {{{"A"[[1]], "A"[[3]]}, {"B"[[1]], "B"[[3]]}, {"C"[[1]], "C"[[3]]}}, {{1[[1]], 1[[3]]}, {2[[1]], 2[[3]]}, {3[[1]], 3[[3]]}}} Expected result should be as in 2nd case. $\endgroup$ – Dragutin Jul 5 '16 at 19:01
  • 3
    $\begingroup$ Perhaps you could point out explicitly why you think that the behavior you observed is not in accordance with operator precedence rules (see e.g. Operator Input Forms and [this answer]).(mathematica.stackexchange.com/a/30430/27951). $\endgroup$ – MarcoB Jul 5 '16 at 19:25
  • $\begingroup$ Tank you. I figured out the point I missed. This was the the way the Map function works on it's arguments. $\endgroup$ – Dragutin Jul 5 '16 at 22:12
  • $\begingroup$ Related: (73762) $\endgroup$ – Mr.Wizard Jul 15 '16 at 10:35
2
$\begingroup$

Perhaps this example helps:

3 # & /@ Sin[#] & /@ {x, y, z}
(*{Sin[3 x], Sin[3 y], Sin[3 z]}*)

vs.

3 # & /@ (Sin[#] & /@ {x, y, z})
(*{3 Sin[x], 3 Sin[y], 3 Sin[z]}*)
$\endgroup$
  • $\begingroup$ OK. this is useful as a starting point for me. But: Trace[3#& /@ Sin[#] &@x] produces {((3#1&)/@Sin[#1]&)[x], (3#1&), /@ Sin[x], Sin[(3#1&)[x]], {(3#1&)[x], 3x}Sin[3x]}. And I don't understan how 3rd step isproduced, because Map[f, expr] is equvalent of f /@ expr, so 3rd step should be 3 [Sin[x]]. Where is the point I miss? $\endgroup$ – Dragutin Jul 5 '16 at 20:36
  • $\begingroup$ @Dragutin Doesn't PrecedenceForm make it clear what is happening? $\endgroup$ – Szabolcs Jul 6 '16 at 8:05
  • $\begingroup$ Yes. Tank you. Now everything is clear. I missunderstood functioning of Map function. $\endgroup$ – Dragutin Jul 6 '16 at 8:35
6
$\begingroup$

To understand grouping and precedence, use HoldForm and PrecedenceForm. I'll insert a screenshot to make the output clearer:

enter image description here

It is useful to know that // has even lower precedence than & and can save you some parentheses.

You probably meant:

({#[[1]], #[[3]]} &) /@ ({#[[1]], #[[2]], #[[3]]} &) /@ {{"A", "B", "C"}, {1, 2, 3}}

It is useful to parenthesize the entire function because & has very low precedence, lower than most other operators. Thus it tends to act on everything preceding it.


Another common mistake with & is using it like this in options:

SomeFunction -> #&

This is really (SomeFunction -> #)& and not SomeFunction -> (#&).


One of the few operators that have even lower precedence than & is //. Thus this is safe:

argument // #&

It groups as argument // (#&) and not as (argument // #)&.


Alternative ways to write you expression are:

Map[{#[[1]], #[[3]]} &] @ Map[{#[[1]], #[[2]], #[[3]]} &] @ {{"A", "B", "C"}, {1, 2, 3}}

{{"A", "B", "C"}, {1, 2, 3}} // Map[{#[[1]], #[[2]], #[[3]]} &] // Map[{#[[1]], #[[3]]} &]

You may or may not find these more readable than the explicitly parenthesized version.

Recently I prefer the latter when doing a lot of chaining.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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