Using a list of tuples in a pure function

It is good practice to check the precedence of code that is not behaving as you expect.

  • One of the easiest ways to do this is to use Ctrl+. to expand the selection outward from the cursor while respecting Mathematica precedence.

  • Converting the expression to StandardForm (Ctrl+Shift+N) will often reveal something about the way Mathematica is parsing your code.

  • Explicitly parenthesize the code using group, supplied below.

  • Wrapping the code with HoldForm[FullForm[ . . . ]] (or appending // FullForm // HoldForm) is a robust but harder to read way to check exactly what Mathematica makes of your code.

  • In this case syntax highlighting should also tell you that something may be wrong, but the highlighting is not entirely reliable. (It may show errors on some correct code.)

  • As a last resort if other methods fail e.g. because your code has syntax errors you can use UndocumentedTestFEParserPacket to see how the Front End is parsing it. Example:

    • Infix form of PutAppend ( >>> ) does not work with variable

In the image below I have converted to StandardForm and also used Ctrl+. to expand the selection. You can see that Mathematica is parsing your Function as (0. &) and that the Map operation is being done before the Set operation.

Mathematica graphics

A function to explicitly parenthesize code:

SetAttributes[group, HoldFirst]

group[expr_] := 
  Replace[
    Unevaluated[expr], 
    x : _[___] :>
      RawBoxes @ RowBox[{"(", ToBoxes @ Unevaluated @ x, ")"}],
    {0, -1}
  ];

Applied to your case:

group[
  value[#[[1]], #[[2]]] = 0. & /@ tuples
]
((value[((#1)[[1]]), ((#1)[[2]])]) = ((0. &) /@ tuples))
  • This may be easier to read than the FullForm as it tends to expand code less.
  • The output of group is valid input which may be used as-is or modified.

This is a precedence issue: You may use

(value[#[[1]], #[[2]]] = 0.) & /@ tuples

instead (ie, explicitly indicate precedence by using brackets).

One way to see what is going on is to notice the colour of the # in the notebook. Or select the & symbol, then press Ctrl+. repeatedly. This progressively selects larger chunks of the expression to which the currently selected expression belongs, and does so in order of precedence. You then will see that 0. & /@ tuples is what mma sees.

You can also use

Trace[value[#[[1]], #[[2]]] = 0. & /@ tuples]

and notice that at some point mma tries to evaluate

value[#1[[1]], #1[[2]]] = {0., 0., 0.}

which is what gives the error (and is due to the precedence issue described above, as it is the result of 0.&/@tuples; tuples is set to a list of three pairs in my case).