MathGroup Archive 2011

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Creating Objects

  • To: mathgroup at smc.vnet.net
  • Subject: [mg122332] Re: Creating Objects
  • From: A Retey <awnl at gmx-topmail.de>
  • Date: Tue, 25 Oct 2011 06:18:48 -0400 (EDT)
  • Delivered-to: l-mathgroup@mail-archive0.wolfram.com
  • References: <j80qhd$afd$1@smc.vnet.net>

Hi,

> Does anyone know how to create Objects in Mathematica, such as those
> produced by LinearModelFit or NDSolve`ProcessEquations? For instance,
> let data be a set of statistical data. Then data["Mean"] would give
> me the mean, data["Values"] would return me the original values,
> etc.
>
> Here is an example from LinearModelFit:
>
> data = {{0, 1}, {1, 0}, {3, 2}, {5, 4}}; lm = LinearModelFit[data, x,
> x]; Save["Model.txt",lm];
>
> The saved output is
>
> lm = FittedModel[{"Linear", {0.18644067796610198,
> 0.6949152542372881}, {{x}, {1, x}}, {0, 0}}, {{1., 1., 1., 1.}}, {{0,
> 1}, {1, 0}, {3, 2}, {5, 4}}, {{1., 0.}, {1., 1.}, {1., 3.}, {1.,
> 5.}}, Function[Null, Internal`LocalizedBlock[{x}, #1], {HoldAll}]]
>
> Which has, basically, only the data and the fitted parameters.
> Nonetheless, by doing lm["FitResiduals"] it computes the residuals
> for me.
>
> In my impression, this is as close as one can get to object-oriented
> programming in Mathematica, and would be a quite useful feature to
> use. I haven't found any documentation on this. Anyone knowns?

It is a common programming pattern in Mathematica to define a "data 
type" by using a special head and then write functions that work with 
that kind of data type by pattern matching for that head, e.g.:

mean[ts_timeseries]:=Mean[timeseries[[1,All,2]]]

ts = timeseries[{{0, 1}, {1, 2}, {2, 4}}]

mean[ts]

You can create the behavior you were asking for by just defining 
corresponding patterns for such a "data type", e.g.:

timeseries[data_]["Mean"] := Mean[data[[All, 2]]]

ts = timeseries[{{0, 1}, {1, 2}, {2, 4}}]

ts@"Mean"

Using patterns as shown above to access certain "properties" of that 
kind of data type is then just syntactic sugar. Using Strings instead of 
symbols is convenient when working with name spaces (Contexts) because 
it avoids shadowing problems with common identifiers.

If you wonder where those rules are stored, that is the SubValues:

SubValues[timeseries]

which are unfortunately only documented very sparse. You will also find 
that for the built in functions you don't find these rules in SubValues:

SubValues[FittedModel]

but that is also true for the more often used DownValues, which are also 
not shown for built in symbols. I can't say whether that means that 
there is necessarily more than such definitions "behind the scene" for 
the built in symbols like FittedModel.

If you are thinking about using that approach you might also want to 
look at Format, which will let you define a convenient formatting for 
your data type, which is especially interesting when working with larger 
datasets which you don't want to be shown within a notebook by accident, 
e.g.:

Format[timeseries[data___]] :=
  Interpretation["timeseries"["<>"], timeseries[data]]

or even:

Format[timeseries[data___]] :=
  Interpretation[
   "timeseries"[ListPlot[data, ImageSize -> Tiny, Frame -> True,
    FrameTicks -> False]], timeseries[data]]

To look at the underlying data, you will not need to save that to a 
file, looking at the InputForm or FullForm is usually good enough:

data = {{0, 1}, {1, 0}, {3, 2}, {5, 4}};
LinearModelFit[data, x, x] // InputForm


hth,

albert




  • Prev by Date: Re: runs slowly?
  • Next by Date: Re: Creating Objects
  • Previous by thread: Re: Creating Objects
  • Next by thread: AbsoluteTime[] runs slowly?