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.
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).