0
$\begingroup$

I'm trying to construct a 'normal' function (with formal parameter) from the FindFit result within a Module context.

While this works on a global level:

In :=

points = Table[{x, 2 x^2 + 3 x + 4 + RandomReal[]}, {x, 1, 10}];
model = a x^2 + b x + c;
fit = FindFit[points, model, {a, b, c}, x];
f[x_] = Evaluate[model /. fit];
f[2]

Out :=

18.473

the same trick in a Module doesn't work.

In :=

Module[{points, model, fit, a, b, c, x, f},
 points = Table[{x, 2 x^2 + 3 x + 4 + RandomReal[]}, {x, 1, 10}];
 model = a x^2 + b x + c;
 fit = FindFit[points, model, {a, b, c}, x];
 f[x_] = Evaluate[model /. fit];
 f[2]
]

Out :=

4.1934 + 3.25034 x$30780002 + 1.97626 x$30780002^2

Looks that the trick with Evaluate doesn't work in a Module context - the argument x of the f is a new variable that is unurelated to the module-scoped x. I would not expect it to work even on a global level. Yet it works.

So the question/problem is: how to get the same effect in Modules in a Wolfram-idiomatic way?

Maybe I've missed the essence of Modules. I just want to protect the outside world from any leakage of assigned variables via lexical scoping, because I found that it is too easy to mess the global environment and destroy symbolical computations in unrelated parts of the script.

$\endgroup$

2 Answers 2

1
$\begingroup$
Clear[f]

f[x_] = Module[
   {points, model, fit, a, b, c, x = x, f},
   (* x=x equates the function's argument to the Module's local \
variable *)
   SeedRandom[1234];
   points =
    Table[
     {x, 2 x^2 + 3 x + 4 + RandomReal[]},
     {x, 1, 10}];
   model = a x^2 + b x + c;
   fit = FindFit[points, model, {a, b, c}, x];
   model /. fit];

f[2]

(* 18.5393 *)
$\endgroup$
0
$\begingroup$

The only issue here is that the x in f[x] is another local variable, different than the one in Module. To solve this in such cases I typically use patterns, like

 Module[{points, model, fit, a, b, c, x, f}, 
 points = Table[{x, 2 x^2 + 3 x + 4 + RandomReal[]}, {x, 1, 10}];
 model = a x^2 + b x + c;
 fit = FindFit[points, model, {a, b, c}, x];
 f[xx_] = model /. fit /. x -> xx;
 f[2]]

This works fine, but I am really looking forward for someone to suggests a more elegant solution, if it exists...

$\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.