27
$\begingroup$

I want to use a list of tuples within a function to make assignments.

Say I want to make assignments of the form

value[i,j] = val

What I have is a list of tuples that give the relevant indices (i,j):

tuples = {{i[1],j[1]},{i[1],j[2]}, ... , {i[imax],j[jmax]}}

What I have found is that this statement will work in Mathematica 8 :

Function[t, value[t[[1]], t[[2]]] = 0.] /@ tuples

But using slots does somehow not work:

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

... gives an error.

Where is the mistake I am making or is there no way to do this using slots? (using Part[#,1] and Part[#,2] will not help either]?

$\endgroup$

2 Answers 2

55
$\begingroup$

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:

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.
$\endgroup$
2
  • 1
    $\begingroup$ I am going to use ctrl-. more! I didn't know it's precedence-aware'that's quite useful. I mostly use ctrl-shift-B to extend my selection and check the balance at the same time. $\endgroup$ Commented Mar 18, 2012 at 20:50
  • $\begingroup$ @gwr Thanking anyone who answered is nice, but don't feel it as a being a requirement: meta.stackexchange.com/questions/17878/… $\endgroup$ Commented Mar 18, 2012 at 20:57
23
$\begingroup$

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

$\endgroup$
3
  • $\begingroup$ I am on the wrong side of this today. I didn't know you were going to expand your answer. $\endgroup$
    – Mr.Wizard
    Commented Mar 18, 2012 at 12:27
  • $\begingroup$ @Mr.Wizard Thank you for discreetly telling me off :) But, in all seriousness, I simply did not think of saying anything other than "add brackets" in the beginning, and then changed my mind. It also annoys me when this happens to me. $\endgroup$
    – acl
    Commented Mar 18, 2012 at 12:33
  • $\begingroup$ I am not telling you off! I am instead amused by the fact that something I supported (which I try not to do as often now) surprised me. I started to make my post an edit to yours, but as it grew longer I decided to post it separately. $\endgroup$
    – Mr.Wizard
    Commented Mar 18, 2012 at 12:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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