47
$\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$
13
  • 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$ Commented Jul 1, 2012 at 17:13
  • $\begingroup$ This may be relevant. $\endgroup$ Commented Jul 1, 2012 at 17:23
  • 3
    $\begingroup$ @WReach, nice to see you around. Undelete your post!! $\endgroup$
    – Rojo
    Commented Jul 1, 2012 at 17:27
  • 1
    $\begingroup$ @LeonidShifrin, you'll make him cry while trying to follow that code! $\endgroup$
    – Rojo
    Commented Jul 1, 2012 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$ Commented Jul 1, 2012 at 17:38

4 Answers 4

45
$\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$
7
  • $\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$ Commented Jul 1, 2012 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
    Commented Jul 1, 2012 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$ Commented Jul 1, 2012 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
    Commented Jul 1, 2012 at 17:44
  • $\begingroup$ @Rojo: hence my "what's a supposed to be?" question in my first comment. ;) $\endgroup$ Commented Jul 1, 2012 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$
2
  • $\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
    Commented Jul 1, 2012 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$ Commented Jul 1, 2012 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 and acknowledge you have read our privacy policy.

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