41
$\begingroup$

I need a table with the elements made of pure functions and list elements. This is a simplified example:

I need a list as:

{a[[1]]*Sin[#]&,a[[2]]*Sin[#]&,a[[3]]*Sin[#]&}

and, my failed try is : Table[a[[i]]*Sin[#]&,{i,3}]

Why is the failure and how can I improve it?

$\endgroup$
  • 2
    $\begingroup$ What's a supposed to be? Do you need something like the result of Function[c, c Sin[#] &] /@ Range[3] or Table[With[{cs = c}, cs Sin[#] &], {c, Range[3]}]? $\endgroup$ – J. M. will be back soon Jul 1 '12 at 17:13
  • $\begingroup$ This may be relevant. $\endgroup$ – Leonid Shifrin Jul 1 '12 at 17:23
  • 3
    $\begingroup$ @WReach, nice to see you around. Undelete your post!! $\endgroup$ – Rojo Jul 1 '12 at 17:27
  • 1
    $\begingroup$ @LeonidShifrin, you'll make him cry while trying to follow that code! $\endgroup$ – Rojo Jul 1 '12 at 17:29
  • 8
    $\begingroup$ My favorites for this problem would still be either Range[3] /. i_Integer :> (a[[i]] Sin[#] &) or Array[Function[x, a[[x]] Sin[#] &], {3}]. $\endgroup$ – Leonid Shifrin Jul 1 '12 at 17:38
40
$\begingroup$

Function has the attribute HoldAll, so the reference to i in the Table expression will not be expanded.

However, you can use With to inject the value into the held expressions:

Table[With[{i = i}, a[[i]]*Sin[#] &], {i, 3}]
{a[[1]] Sin[#1] &, a[[2]] Sin[#1] &, a[[3]] Sin[#1] &}

This issue will be present not only for Function but for all expressions that hold their arguments (via attributes like HoldFirst) -- for example: Plot, Dynamic, RuleDelayed (:>) etc.

The solution using With is mentioned in the tutorial "Introduction To Dynamic / A Good Trick to Know".

$\endgroup$
  • $\begingroup$ If I do a = Range[3]; Table[With[{i = i}, a[[i]] Sin[#] &], {i, 3}], then the a[[i]] remain frozen as Part[] expressions as opposed to whatever the actual values of the a[[i]] are, but maybe this is what the OP wants... $\endgroup$ – J. M. will be back soon Jul 1 '12 at 17:33
  • $\begingroup$ @J.M. It gets substituted when the function is evaluated: Through[Table[With[{i = i}, a[[i]] Sin[#] &], {i, 3}][x]] $\endgroup$ – rm -rf Jul 1 '12 at 17:37
  • $\begingroup$ @R.M, yes, that's true, but it's still a bit jarring for me to see the list of Function[]s still carrying Part[] objects around... $\endgroup$ – J. M. will be back soon Jul 1 '12 at 17:40
  • 1
    $\begingroup$ @JM, the thing is that the OP showed an example where a is undefined. If you try to evaluate it and it's undefined you get an error $\endgroup$ – Rojo Jul 1 '12 at 17:44
  • $\begingroup$ @Rojo: hence my "what's a supposed to be?" question in my first comment. ;) $\endgroup$ – J. M. will be back soon Jul 1 '12 at 17:51
11
$\begingroup$

. . . & is a held expression. (Function has attribute HoldAll.)

Injector pattern to the rescue:

Range@3 /. i_Integer :> (a[[i]] Sin[#] &)

Replace[Range@3, i_ :> (a[[i]] Sin[#] &), 1]

Table[j /. i_ :> (a[[i]] Sin[#] &), {j, 3}]

Or using \[Function] and Array:

Array[i \[Function] (a[[i]] Sin[#] &), 3]

In this case you could do the replacement the other direction but you will need to hold i to protect it from a global value:

Table[a[[i]] Sin[#] & /. HoldPattern[i] -> j, {j, 3}]

Or use Block:

Block[{i},
  Table[a[[i]] Sin[#] & /. i -> j, {j, 3}]
]
$\endgroup$
8
$\begingroup$

This works, but only because j is undefined:

Table[(a[[j]]*Sin[#] &) /. j -> i, {i, 3}]

(if we do j = 5; Table[(a[[j]]*Sin[#] &) /. j -> i, {i, 3}] then it fails; one could localize this with Module to get it to work anyway).

Or, if you hate brevity and compactness:

cF = Function[{j}, a[[j]]*Sin[#] &];
Table[
 cF[j],
 {j, 1, 3}
 ]

Personally I'd use either this last form or WReach's/Rojo's way.

$\endgroup$
  • $\begingroup$ @LeonidShifrin thanks. Yes, that it would need to be localized is what I meant (it's accidental that j is undefined). Bad choice of words, I suppose (and, oops, I hadn't seen your comment... why not an answer?) $\endgroup$ – acl Jul 1 '12 at 18:13
  • $\begingroup$ I've already answered a variant of this question twice (in the links I give in the comments to the question). Trying not to be greedy :-) $\endgroup$ – Leonid Shifrin Jul 1 '12 at 18:15
5
$\begingroup$

With Mathematica 10, you can also do this by

Activate@Table[Inactivate[a[[i]]*Sin[#] &], {i, 3}]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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