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 want to solve an equation with a parameter $a$, and define the result as a function of $a$. It is something like this:

f[a_] := FindRoot[x^2 + 2 x + a == 0, {x, 0.5}]
f[0.2]
(* -> {x -> -0.105573} *)

The equation I want to solve is a large expression, so I do not want to put it explicitly inside the FindRoot. But this does not work:

eq := x^2 + 2 x + a;
f[a_] := FindRoot[eq == 0, {x, 0.5}]
f[0.2]
(* -> FindRoot::nlnum: The function value {1.25 +a} is not a list of numbers with dimensions {1} at {x} = {0.5}. *)

I do not want to define the equation as eq[a], because this equation is also used to do other things, for which it is better to just use eq. The following ways also do not work:

f[a_] := FindRoot[Evaluate[eq] == 0, {x, 0.5}]
f[a_] := Evaluate[FindRoot[eq == 0, {x, 0.5}]]

(However, if we want to solve the above equation analytically, f[a_] := Evaluate[Solve[eq == 0, x]] works, and f[a_] := Solve[Evaluate[eq] == 0, x] does not. How to explain this?)

share|improve this question
    
I think it is a duplicate of: Explicit use of Evaluate not behaving the way I expect it to. Well it is if your question is only " How to explain this?". –  Kuba May 25 at 12:29
add comment

2 Answers 2

up vote 10 down vote accepted

To achieve what you want, you can use the following

eq := x^2 + 2 x + a;
Function[f[a_] := FindRoot[# == 0, {x, 0.5}]][eq]

to define your f.

share|improve this answer
4  
Wow!... Interesting crazy code injection. This is the kind of operations that make new users get in a non excited state about Mathematica. –  Murta May 25 at 14:35
add comment

As an alternative to halirutan's answer, you could define f like this

eq := x^2 + 2 x + a;
Unevaluated[
  f[a_] := FindRoot[eq == 0, {x, 0.5}]
  ] /. OwnValues[eq]

Using Unevaluated in the first argument of ReplaceAll like this is similar to, but avoids, With. You cannot use With here, because With will try to prevent that the a in a_ and the a in eq match.

Note that here eq is never really evaluated, so that we even get a solution if x has a value.

Also ReleaseHold is totally pro (x cannot have a value now)

eq := x^2 + 2 x + a;
Clear@f
ReleaseHold@
 Hold[SetDelayed][f[a_], Hold[FindRoot][eq == 0, {x, 0.5}]]
f[0.2]

{x -> -0.105573}

share|improve this answer
    
Very nice, thanks ;) I was thinking about this but I forgot about OwnValues. I think it's the first time I see it can be really useful :) #newbie –  Kuba May 26 at 20:55
    
@Kuba Well, I saw you use ReleaseHold today too, which is totally pro :P. Actually I could probably use that here :P –  Jacob Akkerboom May 26 at 21:07
    
My version with ReleaseHold was not working, I was not aware about sneaky little With renaming variables. I'm glad you can't see deleted answers :P my is full of pro solutions like: With[{e = eq}, ToExpression[ MakeBoxes[f[a_] := FindRoot[e == 0, {x, 0.5}]] /. "a$_" -> "a_"] ] –  Kuba May 26 at 21:24
    
@Kuba as long as you are the first to answer, it is ok to show off your knowledge of functions that are not really necessary, don't you think :P? I agree With is quite sneaky. The behaviour is mentioned in the docs under With>possible issues, though. –  Jacob Akkerboom May 27 at 7:16
    
oh thank you, now I'm feeling better :P –  Kuba May 27 at 7:19
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.