I'm trying to write a custom function in Mathematica, myFunc[x]
. I want to be able to define properties of the function so that the user can call myFunc[x]["Property"]
and have it return the value stored in Property
.
Basically I'm looking for the same functionality as lmf=LinearModelFit[data,x,x]
where you can use lmf["RSquared"]
to return the correlation coefficient of the fit, but lmf[5]
returns the y value for x=5.
Here's an example of the function that I'm trying to define:
myFunc[data_]:=Module[
{localProperty, x},
localProperty = "123abc";
Return[data+3x];
];
And the output should look like:
(* User enters normal data *)
In[1]: foo = myFunc[5]
Out[1]: 5+3x
(* User enters the name of the property *)
In[2]: foo["localProperty"]
Out[2]: "123abc"
(* User wants to enter a value and evaluate *)
In[3]: foo[3] (* 5+3*3 *)
Out[3]: 14
Is there a way to do this? I believe it's a built-in capability, as witnessed by the symbolic FittedModel
object, but all my searches have so far yielded nothing of use. I've looked at Property
, Option
, Attributes
, and just using If
statements to try and catch the cases where the user types in a property name.
I'm using Mathematica 8.
Thanks,
Edit: Solution Found
Thanks to the guys below, I've found my solution and now have a function that will fit a linear model and plot up the data in one go. I can also extract the model or model parameters by entering different options. Below is the code if anyone is interested.
Clear[ListPlotWithTrendline];
ListPlotWithTrendline[data_, addopts___] := Module[
{lmf, lmfPlot, plot, plots, dr, lmfPlotMinX, lmfPlotMaxX, pos, pr, addopts2, lmfpr, returnValue},
dr = {Min[data[[All, 1]]], Max[data[[All, 1]]]};
(* The workaround to get my 'opts' variable to work with Plot *)
addopts2 = Flatten[{addopts}, 1];
pos = Quiet[Check[Position[Map[StringSplit[ToString[#]][[1]] &, addopts2], "PlotRange"][[1, 1]], 0]];
pr = Quiet[Check[ToExpression[addopts2[[pos, 2]]], dr]];
(* Routine to extract plotrange values for use in the extrapolation *)
lmfpr = If[
pos > 0,
Evaluate[Which[
(* Both X and Y ranges are given *)
Dimensions[pr] == {2, 2}, {pr[[1, 1]], pr[[1, 2]]},
(* The X value is All or Automatic, so we use dataRange *)
pr[[1]] === All || pr[[1]] === Automatic || pr[[1]] === Full, dr,
(* The X range is given and Y is Full, All, or Automatic *)
Length[pr] == 2 && Length[pr[[1]]] == 2, {pr[[1, 1]], pr[[1, 2]]},
(* Only the Y range is given or there was some error, so use the dataRange *)
True, dr
]],
dr];
lmf = LinearModelFit[data, x, x];
lmfPlot = Plot[lmf[x], {x, lmfpr[[1]], lmfpr[[2]]}, #] &@addopts2;
plot = ListPlot[data, #] &@addopts2;
plots = Show[plot, lmfPlot];
(* Define the return values, based on what property the user is interested in. *)
returnValue["FittedModel"] = lmf;
returnValue["Plot"] = plots;
returnValue["FitPlot"] = lmfPlot;
returnValue["ScatterPlot"] = plot;
returnValue["RSquared"] = lmf["RSquared"];
returnValue["Slope"] = lmf[[1, 2, 2]];
returnValue["Intercept"] = lmf[[1, 2, 1]];
Return[returnValue];
];
I'm sure it's not the most efficient or clean code around, but it works so I'm happy. :-) Here's an example: