Re: Creating Objects
- To: mathgroup at smc.vnet.net
- Subject: [mg122334] Re: Creating Objects
- From: Gabriel Landi <gtlandi at gmail.com>
- Date: Tue, 25 Oct 2011 06:19:10 -0400 (EDT)
- Delivered-to: l-mathgroup@mail-archive0.wolfram.com
- References: <j80qhd$afd$1@smc.vnet.net> <201110240914.FAA20534@smc.vnet.net>
Thank you for the feedback guys.
This was quite helpful.
Gabriel
On Oct 24, 2011, at 7:14 AM, Oleksandr Rasputinov wrote:
> On Sun, 23 Oct 2011 11:33:17 +0100, Gabriel Landi <gtlandi at gmail.com>
> wrote:
>
>> Dear MathGroup (and perhaps some Wolfram employees),
>>
>> 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?
>>
>> Sincerely,
>>
>> Gabriel Landi
>>
>
> There isn't actually any special trick to this, as the "objects" are just
> ordinary expressions with OwnValues, UpValues, DownValues, SubValues, etc.
> implementing whatever functionality is required. You can create your
> object by assigning these values inside a Module, amongst other
> approaches. Here's a simple example of a FIFO queue object with named
> ("tagged") sub-queues:
>
> In[1] :=
> TagQueue /: New[TagQueue] :=
> Module[{TagQueue},
>
> (* Define the sequence numbers for the head and tail of each subqueue \
> on the first attempt to access their values. This ensures that an \
> enqueue/dequeue operation cannot fail due to the lack of these \
> definitions and thus avoids the need for a test as to whether a \
> subqueue has been initialized before it is used. *)
> TagQueue[tag_]["Head" | "Tail"] :=
> TagQueue[tag]["Head"] = TagQueue[tag]["Tail"] = 1;
>
> (* A new element is enqueued as in a typical FIFO queue by \
> incrementing the sequence number of the tail element of the \
> corresponding subqueue. A DownValue is then defined for the new item \
> using the sequence number of the tail element as it previously was. *)
> TagQueue /: Enqueue[TagQueue[tag_], expr_] :=
> TagQueue[tag, TagQueue[tag]["Tail"]++] := Unevaluated[expr];
>
> (* Dequeuing an element from a subqueue removes the DownValue for the \
> dequeued element and increments the sequence number of the head \
> element to refer to the next item in the subqueue. *)
> With[{NonEmptyQ = #["Head"] < #["Tail"] &},
> TagQueue /: Dequeue[TagQueue[tag_]?NonEmptyQ] :=
> Block[{val = TagQueue[tag, TagQueue[tag]["Head"]]},
> TagQueue[tag, TagQueue[tag]["Head"]++] =.; val
> ]
> ];
>
> (* If a subqueue is empty (as in default case) then attempts to \
> dequeue from it return $Failed. *)
> TagQueue /: Dequeue@TagQueue[tag_] = $Failed;
>
> (* Mechanism for determining the number of elements currently held in \
> a given subqueue. *)
> TagQueue /: Length@TagQueue[tag_] :=
> TagQueue[tag]["Tail"] - TagQueue[tag]["Head"];
>
> (* Return the TagQueue (with Temporary attribute due to Module). *)
> TagQueue
> ];
>
> In[2] :=
> (* Instantiating the object *)
> q = New[TagQueue]
>
> Out[2] =
> TagQueue$772
>
> In[3] :=
> (* Calling some methods *)
> Enqueue[q["items"], "item 1"]
>
> In[4] :=
> Dequeue@q["items"]
>
> Out[4] =
> "item 1"
>
> In[5] :=
> Enqueue[q["numbers"], #] & /@ Range[10];
>
> In[6] :=
> Length@q["numbers"]
>
> Out[6] =
> 10
>
> In[7] :=
> Dequeue@q["numbers"]
>
> Out[7] =
> 1
>
> In[8] :=
> Table[Dequeue@q["numbers"], {10}]
>
> Out[8] =
> {2, 3, 4, 5, 6, 7, 8, 9, 10, $Failed}
>
> In[9] :=
> (* Destroying the object *)
> Remove@Evaluate[q]
>
> For more information about object-oriented programming in Mathematica
> (defining classes, etc.), I would recommend Roman Maeder's books: either
> "The Mathematica Programmer", or chapter 14 of "Computer Science with
> Mathematica" (see http://www.mathconsult.ch/showroom/pubs/CSM/). You may
> also like to have a look at this page, where the Classes.m file used in
> these books is available for download along with a (brief) usage example:
> http://library.wolfram.com/infocenter/Articles/3243/.
>
- References:
- Re: Creating Objects
- From: "Oleksandr Rasputinov" <oleksandr_rasputinov@hmamail.com>
- Re: Creating Objects