# Return struct from function (with DownValues)

In Mathematica there is a way to create struct-like data type:

struct[myField]=value


I want to return myStruct from a function:

getStruct[input_List] := Module[{struct},
(*populate struct[key]=value from input*)
Return[struct];
];


But when I do:

st = getStruct[myInput];
DownValues[st]


it returns nothing, because it references symbol that was created inside function (like struct\$1299885). I can still access this struct with st["field"], but it's not very usefully without field list.

Basically, I want to pass structs between functions, easily get field list AND easily access values inside those fields. And no, I don't want to do this with global symbols - I want to keep everything in local scope. Is it possible with Mathematica?

I tried this approach because you can easily nest structs within each other and easily access nested fields, like st["field1"]["field2"]. I can also do this with list of rules, but nested access requires a lot of code and looks ugly for something so simple.

Edit: it seems I was missing something very simple. To get list of fields I just needed to run:

DownValues[Evaluate[st]]


Thanks, Leonid.

-
You want DownValues[Evaluate[st]]. Not sure why this was downvoted. – Leonid Shifrin Dec 28 '13 at 15:23
Thank you! This what I was looking for! – EvgenijM86 Dec 28 '13 at 15:31
@LeonidShifrin Quite a lot of downvoting on questions these days. Perhaps a hats byproduct. – Dr. belisarius Dec 28 '13 at 15:37
@LeonidShifrin Strange, I don't see any downvotes. Actually, I only see one vote in total. – Sjoerd C. de Vries Dec 28 '13 at 15:51
more on structs in this post mathematica.stackexchange.com/q/990/66 – faysou Dec 28 '13 at 16:05

Much, if not all, of the desired functionality may be in the new, MMA-10 Association type. In earlier versions, I got a lot of mileage out of the following techniques:

Lists of rules can also act like structs:

ClearAll[x, y, myStruct]
myStruct = {x -> 42, y -> 47}


instead of myStruct.x, which you would do in a C-like syntax, you do x/.myStruct

In[48]:= x /. myStruct
Out[48]= 42


which can be applied to compound expressions

In[49]:= (x^2 + 3 y) /. myStruct
Out[49]= 1905


as opposed to myStruct.x ** 2 + 3 * myStruct.y, as you might have to do in C-like syntax. But, if you want to have dot-notation, and you don't use Dot elsewhere, you can do something like this:

ClearAll[Flip];
Flip[fn_] := Function[{x, y}, fn[y, x]];
Unprotect[Dot];
SetAttributes[Dot, HoldRest];
Dot[rules_, member_] := member /. rules;
Dot[rules_, member_, members__] :=
Fold[Flip@ReplaceAll, List @@ rules, Unevaluated@{member, members}];
Protect[Dot];


and then you get (nested) dots, as in

In[50]:= myStruct.x^2 + 3 myStruct.y
Out[50]= 1905


and

In[59]:= myNewStruct = {a -> 42, b -> {c -> 47, d -> 18}}
Out[59]= {a -> 42, b -> {c -> 47, d -> 18}}

In[60]:= Sin[myNewStruct.a] + myNewStruct.b.c/N[myNewStruct.b.d]
Out[60]= 1.69459


If you have big structs, you can turn them into Dispatch tables for O(1) lookup, like this

In[62]:= {a -> 42, b -> {c -> 47, d -> 18} // Dispatch} // Dispatch
Out[62]= Dispatch[{a -> 42, b -> {c -> 47, d -> 18}}]

In[63]:= Sin[myNewStruct.a] + myNewStruct.b.c/N[myNewStruct.b.d]
Out[63]= 1.69459

-