Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I'm trying to make a function where the input is an expression, but somehow it just won't be evaluated. For example, this little function doesn't work:

test[exp_] := Module[{x}, NestList[Function[x, exp], 2, 3]]
test[x^2]
(* {2, x^2, x^2, x^2} *)

And I would really like this output:

NestList[Function[x, x^2], 2, 3]
(* {2, 4, 16, 256} *)

Can anybody help?

share|improve this question
2  
Try NestList[ #^2 &, 2, 3] –  Artes Oct 27 '12 at 20:23
    
as @Artes points out: test[exp_] := NestList[exp, 2, 3]; test[#^2 &] does the trick? Or following your investigation test[Function[x,x^2]] –  chris Oct 27 '12 at 20:41
1  
b.t.w. welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Read the FAQs! 3) When you see good Q&A, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. ALSO, remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign` –  chris Oct 27 '12 at 20:44
    
Thanks for your answer. But I would really like the input to be test[x^2] or test[2x+5], and not test[Function[x,x^2]]. Isn't that possible? –  Simon Lausen Oct 27 '12 at 21:30
1  
Something to think about: It's not worth writing several lines of code that relies on a more complicated function (e.g., extractPureFunction) just because you don't want to write it as test[#^2&] or test[x^2,x]. The saner thing to do in such cases would be to adopt the style that results in shorter and cleaner coding. –  rm -rf Oct 27 '12 at 22:25
show 4 more comments

2 Answers

up vote 4 down vote accepted

Good question (and one that has bitten me in the past:) The reason for your troubles is the ways scoping of Function works. That's easiest to demonstrate with module however.

Module[{x},x]
(*x$642*)

You see that instead of x x$nnn was returned. For more info I recommend reading this.

Block has the expected behavior by the way:

Block[{x},x]
(*x*)

How about function? The file states: help file

A small test

test[exp_] := Function[x, exp]
test[x^2]
(*Function[x$, x^2]*)

So we see that the formal parameters of function have been renamed to x$ and no longer match the x you have put in. Here are some solutions:

Pass the function to your method

As has been suggested in the comments, you can pass the function as the argument.

ClearAll[test];
test[f_] := Module[{x}, NestList[f, 2, 3]]
test[#^2 &]
test[Function[x, x^2]]

(* ==> {2, 4, 16, 256} *)    
(* ==> {2, 4, 16, 256} *)

Pass the variables along with the expression

ClearAll@test
test[exp_, vars_] := Function[Evaluate@vars, exp]
test[x^2, x]
(*Function[x, x^2]*)

Or inserted into your original example

test[exp_, vars_] := NestList[Function[Evaluate@vars, exp], 2, 3]
test[x^2, x]
(*{2, 4, 16, 256}*)

Oh and if you give your function the HoldAll attribute, then it will not be bothered by existing assignments to x

SetAttributes[test, HoldAll]
test[exp_, vars_] := NestList[Function[vars, exp], 2, 3]
x = 5
test[x^2, x]
(*{2, 4, 16, 256}*)
share|improve this answer
    
Hey, you've almost made it to the first page! congrats! –  rcollyer Oct 28 '12 at 3:02
    
Thank you everybody for your help. My problem is solved. Have made my little function, that will save me a lot of time. Ajasja: I see your point, but the function I gave you was just an example of what was troubling me... Thank you again everybody! –  Simon Lausen Oct 28 '12 at 16:43
add comment

Since @Artes does not seem to want to write up his answer, let me explain why you attempt almost works but not quite.

This works

  test[exp_] := NestList[exp, 2, 3];
  test[Function[x,x^2]];

  (* {2, 4, 16, 256} *)

That doesn't

  test[exp_] := Module[{x}, NestList[Function[x, exp], 2, 3]]
  test[x^2]

because, within the Function, x is a local variable (say x$123) which does not match the one involved in the argument of test when you call test[x^2].

Without pure functions

So if you really want to be able to use a formal expression (rather than a pure function) as an argument to test, you could use the function extractPureFunction that was implemented and discussed in this thread as follows

  test[exp_] := Module[{ff=extractPureFunction[exp]}, NestList[ff, 2, 3]]

so that

  test[x^2]; test[Sin[y]]; test[Sin[x]+x+4];

works. But keep in mind this construction is not bullet proof: for instance

  test[x+y]

doesn't work (because it identifies a function of two parameters x and y).

As I find the extractPureFunction quite useful (I have it in my init.m file) I repeat it here (with as a bonus the getAllVariables function that it uses). The credit goes to Daniel Lichtblau I believe(?)

 headlist = {Or, And, Equal, Unequal, Less, LessEqual, Greater, GreaterEqual, Inequality};
 getAllVariables[f_?NumericQ] := Sequence[]
 getAllVariables[{}] := Sequence[]
 getAllVariables[t_] /; MemberQ[headlist, t] := Sequence[]
 getAllVariables[ll_List] :=Flatten[Union[Map[getAllVariables[#] &, ll]]]
 getAllVariables[Derivative[n_Integer][f_][arg__]] :=
 getAllVariables[{arg}]
 getAllVariables[f_Symbol[arg__]] :=Module[{fvars},
    If[MemberQ[Attributes[f], NumericFunction] || MemberQ[headlist, f],
       fvars = getAllVariables[{arg}],(*else*)fvars = f[arg]]; fvars]
 getAllVariables[other_] := other

 extractPureFunction[expr_] := 
 Module[{vars, func}, vars = getAllVariables[expr];
 If[Length[vars] > 1, vars = Union[vars]];
 func[vars, expr] /. func -> Function]
share|improve this answer
    
because, within the Module, x is a local variable (say x$123) which does not match the one involved in the argument of test when you call test[x^2] I think that Module is not at fault here, but that Function renames it's formal parameters anyway. –  Ajasja Oct 27 '12 at 21:42
    
@Ajasja you are most certainly right. –  chris Oct 27 '12 at 21:43
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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