MathGroup Archive 2011

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

Search the Archive

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/.
>




  • Prev by Date: Re: Creating Objects
  • Next by Date: Error on importing previously saved data file: Get::bigfile
  • Previous by thread: Re: Creating Objects
  • Next by thread: Re: Creating Objects