3
$\begingroup$

Possible Duplicate:
Using pure functions in Table

I have run into a situation that I do not understand when trying to generate a nested list of pure functions. I have the following code.

Table[Function[x, i*x + j], {i, 1, 3}, {j, 1, 4}]

I expected to get a nested list of pure functions, but the values for i and j are not being input. I get

{{Function[x, i x + j], Function[x, i x + j], Function[x, i x + j], 
  Function[x, i x + j]}, {Function[x, i x + j], Function[x, i x + j], 
  Function[x, i x + j], Function[x, i x + j]}, {Function[x, i x + j], 
  Function[x, i x + j], Function[x, i x + j], Function[x, i x + j]}}

What is making this operation fail to behave as I expected?

$\endgroup$
0

4 Answers 4

6
$\begingroup$

Function has HoldAll attribute:

Attributes[Function]
(*{HoldAll, Protected}*)

To see that this is the cause,

SetAttributes[f, HoldAll]
Table[
 f[x, i*x + j],
 {i, 1, 3},
 {j, 1, 4}
 ]
(*
{{f[x, i x + j], f[x, i x + j], f[x, i x + j], 
  f[x, i x + j]}, {f[x, i x + j], f[x, i x + j], f[x, i x + j], 
  f[x, i x + j]}, {f[x, i x + j], f[x, i x + j], f[x, i x + j], 
  f[x, i x + j]}}
*)

EDIT: You can either use With to inject the values,

Table[
  With[{i=i,j=j},Function[x, i*x + j]],
  {i, 1, 3},
  {j, 1, 4}
  ] 

or, more perversely,

Table[
  function[x, i*x + j],
  {i, 1, 3},
  {j, 1, 4}
  ] /. function -> Function

or even

Block[{Function},
 Table[
  Function[x, i*x + j],
  {i, 1, 3},
  {j, 1, 4}
  ]
 ]
$\endgroup$
2
  • 1
    $\begingroup$ It's probably good to point out that the second and third methods (function -> Function and Block) are safe only if the Function contains an expression that does not evaluate. $\endgroup$
    – Szabolcs
    Commented Nov 8, 2012 at 20:41
  • $\begingroup$ @Szabolcs right, they effectively sidestep the HoldAll completely $\endgroup$
    – acl
    Commented Nov 8, 2012 at 20:44
4
$\begingroup$

Function has attribute HoldAll, which means it doesn't evaluate its arguments.

Table localizes the variables in each iteration much like Block does. This means, it just temporarily gives the variables the value that corresponds to the iteration, and then run the contained code.

So, try

x = 8; Function[i, i x]

and see that you get Function[i, i x], where the x has not been replaced.

Try

Array[{i, j} \[Function] x \[Function] i x + j, {3, 4}]
$\endgroup$
3
$\begingroup$

You already have 3 answers including one accepted one. Notwithstanding, naively I would have done

Table[Function[x, i*x + j // Evaluate], {i, 1, 3}, {j, 1, 4}]

which works and follows your syntax.

PS: I replaced Release by Evaluate to avoid unnecessary confusion.

$\endgroup$
3
  • $\begingroup$ That's an interesting tactic. Do you think ReleaseHold would work? My Mathematica 8 help tells me that Release was superseded by Evaluate and ReleaseHold. $\endgroup$ Commented Nov 8, 2012 at 22:08
  • 1
    $\begingroup$ I didn't know the function Release. Apparently it's the old and deprecated name for Evaluate. @Carl Evaluate will work only at the first level of the head with a Hold... attribute. Function[x, i*x + j // Evaluate] will work here, but Function[x, Evaluate[i]*x + Evaluate[j]] will not. This is because Evaluate is implemented as a special exception to Hold... attributes: when the evaluator sees something with HoldAll, it will check if there's an Evaluate inside, but only at the first level (it won't do a potentially slow deep search). $\endgroup$
    – Szabolcs
    Commented Nov 8, 2012 at 22:23
  • 1
    $\begingroup$ @Szabolcs, as I said a number of times before, Release[] is a sort of hybrid of Evaluate[] and ReleaseHold[]; that is, it was the useful function before the devs at Wolfram finally decided to split Release[]'s functionality into the two modern functions Evaluate[] and ReleaseHold[]. $\endgroup$ Commented Nov 8, 2012 at 23:29
2
$\begingroup$

I encountered this problem myself a while ago. The evaluation order of the Table, which the docs say "usually" has the iterative variable replaced first, is a bit weird here. I suppose that this is a case when they're not replaced first.

However, they are replaced for With. You can use this to your advantage with (get it?) this:

Table[With[{a = i, b = j}, Function[x, a*x + b]], {i, 1, 3}, {j, 1, 4}]

Then:

%[[1, 1]][3]
(* 4 *)
$\endgroup$
1
  • 2
    $\begingroup$ you can also do With[{i = i, j = j}, Function[x, i*x + j]] $\endgroup$
    – acl
    Commented Nov 8, 2012 at 20:29

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