Function in Table

43

15

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?

yulinlinyu

Posted 2012-07-01T17:10:38.567

Reputation: 4 555

Has anyone mentioned Evaluate?"Table[Evaluate[a[[i]]*Sin[#]]&,{i,3}]" – None – 2014-02-03T15:50:40.857

2What'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]}]? – J. M.'s ennui – 2012-07-01T17:13:41.803

This may be relevant. – Leonid Shifrin – 2012-07-01T17:23:06.443

@R.M, that puts the constant outside the Function[] as opposed to the inside, no? – J. M.'s ennui – 2012-07-01T17:23:07.540

3@WReach, nice to see you around. Undelete your post!! – Rojo – 2012-07-01T17:27:47.047

Also, I illustrate various techniques of generating lists of pure functions with injected elements (very close to what you ask for), in this answer.

– Leonid Shifrin – 2012-07-01T17:27:48.310

1@LeonidShifrin, you'll make him cry while trying to follow that code! – Rojo – 2012-07-01T17:29:24.127

@Rojo But the part on pure functions is in the middle of the post, and independent on anything else - have a look. – Leonid Shifrin – 2012-07-01T17:30:15.297

@LeonidShifrin I see. Then you'll make him happy :) – Rojo – 2012-07-01T17:31:38.713

Rojo, JM: you're right. Heh, I need breakfast – rm -rf – 2012-07-01T17:31:51.083

Wow, Rojo and WReach posted at the exact same time, down to the second! – rm -rf – 2012-07-01T17:32:51.130

@R.M. Apparently, one second granuarity is not enough (too coarse). – Leonid Shifrin – 2012-07-01T17:34:21.597

8My favorites for this problem would still be either Range[3] /. i_Integer :> (a[[i]] Sin[#] &) or Array[Function[x, a[[x]] Sin[#] &], {3}]. – Leonid Shifrin – 2012-07-01T17:38:34.043

Answers

43

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

WReach

Posted 2012-07-01T17:10:38.567

Reputation: 62 787

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... – J. M.'s ennui – 2012-07-01T17:33:46.933

@J.M. It gets substituted when the function is evaluated: Through[Table[With[{i = i}, a[[i]] Sin[#] &], {i, 3}][x]] – rm -rf – 2012-07-01T17:37:21.330

@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... – J. M.'s ennui – 2012-07-01T17:40:17.923

1@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 – Rojo – 2012-07-01T17:44:13.660

@Rojo: hence my "what's a supposed to be?" question in my first comment. ;) – J. M.'s ennui – 2012-07-01T17:51:13.370

@J.M. Yes, it's almost like SetDelayed in that changing a changes the functions. Useful to know, but can create unexpected results if one weren't aware of it – rm -rf – 2012-07-01T17:55:11.750

@Rojo et al: thanks for undelete :) – WReach – 2012-07-01T18:32:53.973

11

. . . & 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}]
]

Mr.Wizard

Posted 2012-07-01T17:10:38.567

Reputation: 259 163

8

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.

acl

Posted 2012-07-01T17:10:38.567

Reputation: 19 146

@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?) – acl – 2012-07-01T18:13:03.483

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 :-) – Leonid Shifrin – 2012-07-01T18:15:10.250

5

With Mathematica 10, you can also do this by

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

matheorem

Posted 2012-07-01T17:10:38.567

Reputation: 14 483