5
$\begingroup$

Why are the following not equivalent:

Map[Line, Map[(Print[#]; #) &, {{{2, 1}, {1, 1}}, {{-2, 1}, {3, 1}}}]]

which produces

{{2,1},{1,1}}
{{-2,1},{3,1}}
{Line[{{2, 1}, {1, 1}}], Line[{{-2, 1}, {3, 1}}]}

and:

Line /@ (Print[#]; #) & /@ {{{2, 1}, {1, 1}}, {{-2, 1}, {3, 1}}}

which produces

{{2,1},{1,1}}
{{-2,1},{3,1}}
{{Line[{2, 1}], Line[{1, 1}]}, {Line[{-2, 1}], Line[{3, 1}]}}
$\endgroup$
2
  • $\begingroup$ Does the Documentation Center page tutorial/OperatorInputForms, with its listing in order of precedence, help? $\endgroup$
    – murray
    Jan 4, 2015 at 4:17
  • $\begingroup$ Related: (3143), (30425) $\endgroup$
    – Mr.Wizard
    Jan 19, 2015 at 17:09

2 Answers 2

10
$\begingroup$

The behaviour we see is due to the precedence of &, which is much lower than the precedence of /@. As a consequence, the expression Line /@ (Print[#]; #) is bound tightly together by the high precedence /@ infix operator, yielding the single argument to the low precedence & postfix operator. This means that the second expression is interpreted as (note the added parentheses prior to the second /@):

(Line /@ (Print[#]; #) &) /@ {{{2, 1}, {1, 1}}, {{-2, 1}, {3, 1}}}

which is equivalent to:

Map[Line /@ (Print[#]; #) &, {{{2, 1}, {1, 1}}, {{-2, 1}, {3, 1}}}]

or

Map[Map[Line, (Print[#]; #) &], {{{2, 1}, {1, 1}}, {{-2, 1}, {3, 1}}}]

This is manifestly different from the first expression in the question.

One way to see this in the front-end is to place the cursor somewhere within Print and then extend the selection using CTRL+. repeatedly. With each key press, the selection grows outward to show how subexpressions group together due to precedence. Repeatedly double-, triple-, quadruple-clicking, etc. on a selection point will also extend the selection to show precedence.

Another way to see how the expression is interpreted is to inspect its full-form:

Line /@ (Print[#];#)& /@ {{{2,1},{1,1}},{{-2,1},{3,1}}} // FullForm // HoldForm

(*
  Map[
    Function[Map[Line, CompoundExpression[Print[Slot[1]],Slot[1]]]],
    List[List[List[2,1],List[1,1]],List[List[-2,1],List[3,1]]]]
*)

The Wolfram Language documentation has a section that details operator precedence.

$\endgroup$
1
  • 1
    $\begingroup$ +1 for control-dot. I didn't know about that until now! Thanks. $\endgroup$
    – Mark Adler
    Jan 3, 2015 at 22:42
1
$\begingroup$

Actually,

Map[Line, Map[(Print[#]; #) &, {{{2, 1}, {1, 1}}, {{-2, 1}, {3, 1}}}]]

is equivalent to

Line /@ ((Print[#]; #) & /@ {{{2, 1}, {1, 1}}, {{-2, 1}, {3, 1}}})

with both producing

{{2,1},{1,1}}
{{-2,1},{3,1}}
{Line[{{2, 1}, {1, 1}}], Line[{{-2, 1}, {3, 1}}]}

Note the extra pair of parentheses that I added. They are necessary so that Line in the expression using /@ is mapped to all of ((Print[#]; #) & /@ {{{2, 1}, {1, 1}}, {{-2, 1}, {3, 1}}}), as it is in the expression using Map explicitly.

$\endgroup$
2
  • $\begingroup$ Okay, but how is Line mapped without the parentheses? Are the two not supposed to be equivalent? How is the result produced in the case of Line /@ (Print[#]; #) & /@ {{{2, 1}, {1, 1}}, {{-2, 1}, {3, 1}}}? I would really appreciate an explanation. $\endgroup$
    – d125q
    Jan 3, 2015 at 21:04
  • $\begingroup$ Run Trace on the three expressions to see the differences. $\endgroup$
    – bbgodfrey
    Jan 3, 2015 at 21:06

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