Using symbols to store data and object-like functions
-

Here are interesting functions to use symbols like objects. (I originally posted these thoughts in [What is in your Mathematica tool bag?][1]).

The post has grown quite big over time as I used it to record ideas.  

It's divided into three parts, one describing the function Keys, another one where properties and functions are stored in a symbol created inside a Module, thus mimicking objects in object oriented programming and a last one where objects have the form ObjectHead[object].

**Introduction**

It is already well known that you can [store data in symbols][2] and quickly access them using DownValues.

    (*Write/Update*)
    mysymbol["property"]=2;
    (*Access*)
    mysymbol["property"]
    (*Delete*)
    Unset[mysymbol["property"]]

It is similar to a hashtable, new rules are added for each property to DownValues[mysymbol]. But internally, from what I understood, rules of a symbol are stored as a hashtable so that Mathematica can quickly find which one to use. The key ("property" in the example) doesn't need to be a string, it can be any expression (which can be used to cache expressions, as also shown in the post quoted above).

**Keys**

You can access the list of keys (or properties) of a symbol using these functions based on what dreeves once [submitted][3] (I was quite lucky to have found his post early in my Mathematica learning curve, because it allowed me to work on functions working with lots of different arguments, as you can pass the symbol containing the stored properties to a function and see which keys this symbol contains using Keys):

    SetAttributes[RemoveHead, {HoldAll}];
    RemoveHead[h_[args___]] := {args};
    NKeys[_[symbol_Symbol]]:=NKeys[symbol]; (*for the head[object] case*)
    NKeys[symbol_] := RemoveHead @@@ DownValues[symbol(*,Sort->False*)][[All,1]];
    Keys[symbol_] := Replace[NKeys[symbol], {x_} :> x, {1}];

Usage example of Keys

    a["b"]=2;
    a["d"]=3;
    Keys[a]

    (*getting the values associated with the keys of the a symbol*)
    a /@ Keys[a]

If you use multiple keys for indexing a value

    b["b",1]=2;
    b["d",2]=3;
    Keys[b]

    (*getting the values associated with the keys of the b symbol*)
    b @@@ Keys[b]

**PrintSymbol**

I use this function a lot to display all infos contained in the DownValues of a symbol (which uses one key per value):

    PrintSymbol[symbol_] :=
      Module[{symbolKeys=Keys[symbol]},
        TableForm@Transpose[{symbolKeys, symbol /@ symbolKeys}]
      ];

    PrintSymbol[a]

**Replacing a part of a list stored in a symbol**

The following would produce an error

    mysymbol["x"]={1,2};
    mysymbol["x"][[1]]=2

One way to do this would be either to introduce a temporary variable for the list stored in mysymbol["x"], modify it and put it back in mysymbol["x"] or, if possible, use a syntax like

    mysymbol["x"] = ReplacePart[mysymbol["x"], 1 -> 2]

Interestingly some answers to this post http://mathematica.stackexchange.com/q/7214/66 deal with this issue in a O(1) way (compared to the O(n) complexity of ReplacePart where a new list is created to modify it afterwards).

**Creation of objects with integrated functions**

Finally here is a simple way to create a symbol that behaves like an object in object oriented programming, different function syntaxes are shown :

    Options[NewObject]={y->2};
    NewObject[OptionsPattern[]]:=
      Module[{newObject,aPrivate = 0,privateFunction},
        (*Stored in DownValues[newObject]*)
        newObject["y"]=OptionValue[y];
        newObject["list"] = {3, 2, 1};

        (*Private function*)
        privateFunction[x_]:=newObject["y"]+x;
        
        (*Stored in UpValues[newObject]*)
        function[newObject,x_] ^:= privateFunction[x];
        newObject /: newObject.function2[x_] := 2 newObject["y"]+x;

        (* "Redefining the LessEqual operator" *)
        LessEqual[newObject,object2_]^:=newObject["y"]<=object2["y"];

        (* "Redefining the Part operator" *)
        Part[newObject, part__] ^:= newObject["list"][[part]];

        (*Syntax stored in DownValues[newObject], could cause problems by 
          being considered as a property with Keys*)
        newObject@function3[x_] := 3 newObject["y"]+x;

        (*function accessing a "private" variable*)
        functionPrivate[newObject] ^:= aPrivate++;

        (* "Redefining the [ ] operator" *)
        newObject[x_] := x newObject["list"];

        (*Format*)
        Format[newObject,StandardForm]:="newObject with value y = "~~ToString[newObject["y"]];

        newObject
      ];

Properties are stored as DownValues and methods as delayed Upvalues (except for the [ ] redefinition also stored as DownValues) in the symbol created by Module that is returned. I found the syntax for function2 that is the usual OO-syntax for functions in [Tree data structure in Mathematica][4].

**Private variable**

The variables aPrivate can be seen as a private variable as it is only seen by the functions of each newObject (you wouldn't see it using Keys). Such a function could be used to frequently update a list and avoid the issue of the previous paragraph. 

If you wanted to DumpSave newObject you could know which aPrivate$xxx variable to also save by using the depends function of Leonid Shifrin described in the post http://mathematica.stackexchange.com/q/4343/66. 

    depends[NewObject[]]

Note that xxx  is equal to $ModuleNumber - 1 when this expression is evaluted inside Module so this information could be stored in newObject for later use.

Similarly the function privateFunction can be seen as an internal function that cannot to be called explicitely by the user.

**Other way for storing functions in a different symbol**

You could also store the function definition not in newObject but in a type symbol, so if NewObject returned type[newObject] instead of newObject you could define function and function2 like this 
outside of NewObject (and not inside) and have the same usage as before. See the second part of the post below for more on this.

    (*Stored in UpValues[type]*)
    function[type[object_], x_] ^:= object["y"] + x;
    type /: type[object_].function2[x_] := 2 object["y"]+x;

    (*Stored in SubValues[type]*)
    type[object_]@function3[x_] := 3 object["y"]+x;

**Usage example**

    x = NewObject[y -> 3]
    x // FullForm

    x["y"]=4
    x@"y"

    function[x, 4]
    x.function2[5]
    x@function3[6]

    (*LessEqual redefinition test with Sort*)
    z = NewObject[]
    {x["y"],z["y"]}
    l = Sort[{x,z}, LessEqual]
    {l[[1]]["y"],l[[2]]["y"]}

    (*Part redefinition test*)
    x[[3]]

    (*function accessing a "private" variable*)
    functionPrivate[x]

    (*[ ] redefinition test*)
    x[4]
    
**Reference/Extension**  

For a list of existing types of values each symbol has, see http://reference.wolfram.com/mathematica/tutorial/PatternsAndTransformationRules.html and http://www.verbeia.com/mathematica/tips/HTMLLinks/Tricks_Misc_4.html.

You can go further if you want to emulate object inheritance by using a package called InheritRules available here
http://library.wolfram.com/infocenter/MathSource/671/

Further ideas when storing functions in a head symbol
--

This second part of the post uses some ideas exposed previously but is independent, we redevelop equivalent ideas in a slightly different framework.

The idea is to use DownValues for storing properties in different symbols corresponding to objects and UpValues for storing methods in a unique head symbol (MyObject in the example below). We then use expressions of the form MyObject[object].

Here is a summary of what I currently use.

**Constructor**

    Options[MyObject]={y->2};
    MyObject[OptionsPattern[]]:=
       Module[{newObject,aPrivate = 0},
          newObject["y"]=OptionValue[y];
          newObject["list"] = {3, 2, 1};

          (*Private function*)
          privateFunction[]:=aPrivate++;

          (*function accessing a "private" variable*)
          functionPrivate[MyObject[newObject]] ^:= privateFunction[];

          MyObject[newObject]
       ];

MyObject is used as "constructor" and as head of the returned object (for example MyObject[newObject$23]). This can be useful
for writing functions that take into account the head of an object. For example     

    f[x_MyObject] := ...

Properties (like the value corresponding to the key "y") are stored as DownValues in a newObject symbol created by Module whereas functions will be stored in the MyObject symbol as UpValues.

**Private variable**

functionPrivate in the constructor definition has access to the "private" variable aPrivate. It is stored as UpValues of MyObject but with a dependency on each newObject symbol created in Module (which breaks the indendance between data stored in newObject and methods stored in MyObject that other function syntaxes described below share). It must be defined in Module contrary to other kind of functions described below, so that the symbols newObject and aPrivate generated in the same Module are stored in a same rule and thus can "see" each other.

On the other hand privateFunction can be seen as an internal function that cannot to be called explicitely by the user.

**Some methods stored as UpValues in MyObject (different syntaxes are shown)**  

    (*Stored in UpValues[MyObject]*)
    function[MyObject[object_], x_] ^:= object["y"] + x;
    MyObject/: MyObject[object_].function2[x_] := 2 object["y"]+x;

    (* "Redefining the LessEqual operator" *)
    LessEqual[MyObject[object1_],MyObject[object2_]]^:=object1["y"]<=object2["y"];

    (* "Redefining the Part operator" *)
    Part[MyObject[object_], part__] ^:= object["list"][[part]];
    
    myGet[MyObject[object_], key_] ^:= object[key];
    mySet[MyObject[object_], key_, value_] ^:= (object[key]=value);  
    (*or*) 
    MyObject/: MyObject[object_].mySet[key_, value_] := (object[key]=value);  

**Methods stored as SubValues in MyObject**  

A method stored to easily access the properties of an object. We restrict here key to be a string in order not to interfere with other functions defined as SubValues.

    MyObject[object_Symbol][key_String] := object[key];

Another function stored in SubValues[MyObject]

    MyObject[object_]@function3[x_] := 3 object["y"]+x;

Redefinition of the [ ] operator

    MyObject[object_][x_] := x object["list"];

**"Static" variable**

Similarly to what is used for a private variable, a variable can be shared among all the objects of a similar class using a following definition for the function that accesses it.
(Such variables use the keyword static in C++-like languages)

    Module[{staticVariable=0},
       staticFunction[MyObject[object_]]^:=(staticVariable+=object["y"]);
    ]

**Using methods from another class**

Let's say that Class1 and Class2 share a common method named function. If we have an object Class1[class1Object] and want to use the function version of Class2 we can do this using something like 

    Class2[class1Object].function[]

**Format**

You can format the way the object is displayed with something like this:

    Format[MyObject[object_Symbol],StandardForm]:="MyObject with value y = "~~ToString[object["y"]];

**Creating an object**

    x = MyObject[y->3]

**Test of the different functions**

    x // FullForm

    function[x, 2]
    x.function2[3]
    x@function3[4]

    x["y"]
    x@"y"

    (*LessEqual redefinition test with Sort*)
    z = MyObject[]
    {x["y"],z["y"]}
    l = Sort[{x,z}, LessEqual]
    {l[[1]]["y"],l[[2]]["y"]}

    (*Part redefinition test*)
    x[[3]]

    (*function accessing a "private" variable*)
    functionPrivate[x]

    (*[ ] redefinition test*)
    x[4]

    (*static function example*)
    staticFunction[x]
    staticFunction[z]

**Update properties**

*Using ObjectSet*

To update the "y" property of z you can use this (or use a setter function like mySet defined above)

    ObjectSet[(_[symbol_Symbol]|symbol_),key_,value_]:=symbol[key]=value;
    ObjectSet[z,"y",3]

If an object is of the kind MyObject[object] then value will be assigned to object[key] (DownValues of object) instead of being assigned to MyObject[object][key] (SubValues of MyObject whereas I want functions to be in general stored as UpValues of MyObject and properties as DownValues of object).

*Using object in MyObject[object] directly*

Another way that doesn't involve another function is to do

    z[[1]]["y"] = 4


*Using mySet (defined above)*

    z.mySet["y",5]

*Using Set*

You can automate ObjectSet by overloading Set in a dynamic environment for example. See this post for more details http://mathematica.stackexchange.com/questions/1162/alternative-to-overloading-set
    
	ClearAll[withCustomSet];
	SetAttributes[withCustomSet, HoldAll];
	withCustomSet[code_] :=
		Internal`InheritedBlock[{Set},
			Unprotect[Set];
			Set[symbol_[key_],value_]:=
			   Block[{$inObjectSet=True},
              ObjectSet[symbol,key,value]
	   ]/;!TrueQ[$inObjectSet];
			Protect[Set];
			
			code
		];

So that you can do 

    withCustomSet[
       z["y"] = 6
    ]
    function[z, 2]

This syntax works also for sub-objects

    withCustomSet[
       z["u"]=MyObject[];
       z["u"]["i"]=2
    ]

    PrintSymbol[z["u"]]


  [1]: http://stackoverflow.com/a/6245166/884752
  [2]: http://reference.wolfram.com/mathematica/tutorial/MakingDefinitionsForIndexedObjects.html
  [3]: http://stackoverflow.com/a/154704/884752
  [4]: http://stackoverflow.com/questions/6097071/tree-data-structure-in-mathematica/6097444#6097444