Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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.

share|improve this question
2  
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. –  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
1  
more on structs in this post mathematica.stackexchange.com/q/990/66 –  faysou Dec 28 '13 at 16:05

1 Answer 1

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
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.