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