Tom Lieber's Microblog

Custom data structures in Mathematica

Dear Future Tom,

One day, you will once again write yourself into a corner with code like this:

makeLife[dna_] := <| "dna" → dna |>;
hasWings[life_] := wingsQ[grow[life["dna"], Quantity[1/3, "Lifetime"]]];
reproduce[life1_, life2_] := makeLife[mix[life1["dna"], life2["dna"]]];

You will realize your code is slow because you’re recomputing derived properties of these objects unnecessarily, and start to fret over how you store intermediate values. You will worry about types. You will become frustrated, but remember the pattern you learned in class:

makeLife[dna_] := Life[<| "dna" → dna |>];

(* This getter will help you to worry less about the data being normalized. And it checks the type! *)
getDna[life_Life] := life[[1]]["dna"];

(* Look, this expensive derived property is memoized! *)
ClearAll[hasWings];
hasWings[life_] := hasWings[life] = wingsQ[grow[getDna[life], Quantity[1/3, "Lifetime"]]];

(* When you change the way DNA is stored, this code will still work, man! *)
reproduce[life1_, life2_] := makeLife[mix[getDna[life1], getDna[life2]]];