Mathematica: SUPER TIP: Use CreateUUID[] to trigger recalculation against Once[] to create a flexible optionally caching function! (May incur a memory penalty, consider also using a 'loc' persistence location.)

Webel IT Australia promotes the amazing Mathematica tool and the powerful Wolfram Language and offers professional Mathematica services for computational computing and data analysis. Our Mathematica tips, issue tracking, and wishlist is offered here most constructively to help improve the tool and language and support the Mathematica user community.
DISCLAIMER: Wolfram Research does not officially endorse analysis by Webel IT Australia.
Icon class
icon_class
far fa-sticky-note
icon_class_computed
far fa-sticky-note
Note kind
Policy level
Keywords

Ever wanted to use Once (once-per-session evaluation) for efficiency within a computationally expensive function but you still wanted to be able to override it easily sometimes within a session? This is how! CreateUUID[] to the rescue:

In this demo a Pause is used so you can tell whether it's caching:

fCache[a_, $uuid:(_String|None):None] := 
Once[($uuid; Pause[a]; a^2)];
Create a uuid and pass it first time (or use the default None) :
i: $uuid1 = CreateUUID[]
o: f8deb36b-b2a5-4538-a782-9631425696da 

The first time you call fCache it will run, which you can tell here in this demo by the Pause:

i: fCache[2,$uuid1]
(* ... wait 2 seconds ... *)
o: 4

[BTW: You can also do a Print[$uuid] to see it happening better, but not in production code of course.]

The next time you call fCache it will just return the pre-computed result under control of Once:

i: fCache[2,$uuid1]
(* "instantaneous", well almost *)
o: 4  

In fact you don't need to pass in that $uuid every time, since Once looks after it for you:

i: fCache[2]
(* "instantaneous" again, well almost *)
o: 4  
To force it to re-compute again, just feed it a fresh UUID using CreateUUID[]:
i: fCache[2,CreateUUID[]]
(* ... wait 2 seconds again ... *)
o: 4

Note that in the example as shown, the '$uuid' isn't doing anything other than forcing the Once to re-trigger. It will also work if you have another delegate function with that uses the '$uuid' somehow (possible also with UUID-driven Once-caching):

fOuterCache[i_Integer, $uuid:(_String|None):None] := 
Once[ 
 fUuidToInteger[$uuid] + i
];

The Webel libraries for Mathematica have a short alias uu[] for CreateUUID[], because this UUID-driven Once-caching is used often in combination with the Webel ADT recipe.

So why would one want to do this UUID-driven Once-caching?

A few cases:

  • You are reloading changed/edited function code during development, but you want it to otherwise cache most of the time (not just "once"). Very handy.
  • Your function depends on something randomly generated internally, as used in the Wolfram online help example for Once using Random, which example is of course not pure stateless functional, but it's a very nice demo.
  • You are very, very naughty, and your function is deliberately not pure stateless functional, so the result could change because of other happenings elsewhere each time it is invoked, and that doesn't worry you, you can live perfectly well with that and still look yourself in the mirror, even if it's not "the Mathematica way".
  • You are proudly and knowingly and with full awareness using the stateful capabilities of the user-contributed MTools package for (some) OO in Mathematica, but you want control over when to "hit" the state (also useful during development). Because you know that state is not "evil" per se if you know how to use it well. (And besides, use of some aspects of OO does not automatically imply use of its stateful capabilities, but that's another story for another time, and not really relevant here.)
CAUTION: Once-caching may incur a memory penalty!
Consider also the option of using a explicit 'loc' persistence location:
Once[expr, loc]

This UUID-driven Once caching trick is used in the Webel recipe for Abstract Data Type (ADT) pseudo-classes with inheritance:
Relates to
Related notes
Related notes (backlinks)
Related snippets (extracts)
Visit also
Visit also (backlinks)
External links