Function Repository Resource:

OnceUnlessFailed

Source Notebook

Equivalent to using Once, but will only cache results if evaluation was successful

Contributed by: Richard Hennigan (Wolfram Research)

ResourceFunction["OnceUnlessFailed"][expr]

is equivalent to Once[expr], but does not cache results if expr evaluates to a failure or generates a message.

ResourceFunction["OnceUnlessFailed"][expr,loc]

caches results in the persistence location loc.

Details and Options

An evaluation is considered successful if FailureQ returns false and it does not generate any messages during evaluation.
When first used in a session, OnceUnlessFailed[expr] evaluates expr and returns the result.
Subsequent uses of OnceUnlessFailed[expr] do not evaluate expr again, and return the result from when expr was first evaluated.
OnceUnlessFailed has attribute HoldFirst.
OnceUnlessFailed[expr] is equivalent to OnceUnlessFailed[expr,"KernelSession"].
A persistence location is given as PersistenceLocation["type"] or "type".
Unset[OnceUnlessFailed[expr]] or Unset[OnceUnlessFailed[expr,loc]] removes any stored value for expr.
OnceUnlessFailed has the following options:
ExpirationDateNonewhen the cache should expire
PersistenceTimeNonehow long the cache should persist
If OnceUnlessFailed[expr,] is evaluated after a cached result is specified to have expired, then expr will be evaluated again.

Examples

Basic Examples (2) 

Evaluate an expression inside OnceUnlessFailed:

In[1]:=
ResourceFunction["OnceUnlessFailed"][Print["ping"]; RandomReal[]]
Out[1]=

Any subsequent evaluations of OnceUnlessFailed[expr] simply returns the previous result:

In[2]:=
ResourceFunction["OnceUnlessFailed"][Print["ping"]; RandomReal[]]
Out[2]=

If a message is generated during evaluation, results are not cached:

In[3]:=
ResourceFunction["OnceUnlessFailed"][1/0; Print["ping"]; RandomReal[]]
Out[3]=
In[4]:=
ResourceFunction["OnceUnlessFailed"][1/0; Print["ping"]; RandomReal[]]
Out[4]=

Scope (3) 

Retrieve the ResourceFunction:

In[5]:=
ResourceFunction["OnceUnlessFailed"]
Out[5]=

Retrieve the ResourceObject:

In[6]:=
ResourceObject["OnceUnlessFailed"]
Out[6]=

Specify an alternate persistence location:

In[7]:=
ResourceFunction["OnceUnlessFailed"][RandomReal[], "FrontEndSession"]
Out[7]=

The value is remembered even after a kernel restart:

In[8]:=
Quit[]
In[9]:=
ResourceFunction["OnceUnlessFailed"][RandomReal[], "FrontEndSession"]
Out[9]=

Generalizations & Extensions (3) 

Even if no message is generated, a result will not be cached if the output results in a failure (as determined by FailureQ):

In[10]:=
count = 0;
tryTwice[] := If[Echo[++count] === 2, "Success", $Failed];
In[11]:=
ResourceFunction["OnceUnlessFailed"][tryTwice[]]
Out[11]=

Since the first evaluation resulted in a failure, the result is not cached:

In[12]:=
ResourceFunction["OnceUnlessFailed"][tryTwice[]]
Out[12]=

The results are now cached:

In[13]:=
ResourceFunction["OnceUnlessFailed"][tryTwice[]]
Out[13]=

Options (3) 

PersistenceTime (2) 

Specify that the result of OnceUnlessFailed should be remembered only for 5 seconds:

In[14]:=
ResourceFunction["OnceUnlessFailed"][Now, PersistenceTime -> 5]
Out[14]=
In[15]:=
Pause[1]; ResourceFunction["OnceUnlessFailed"][Now, PersistenceTime -> 5]
Out[15]=

After the time specified has elapsed, the value is recomputed:

In[16]:=
Pause[4]; ResourceFunction["OnceUnlessFailed"][Now, PersistenceTime -> 5]
Out[16]=

ExpirationDate (1) 

Specify that a remembered value should expire at the beginning of next year:

In[17]:=
ResourceFunction["OnceUnlessFailed"][Now, "Local", ExpirationDate -> NextDate["Year"]]
Out[17]=

Applications (2) 

Use cached cloud operations even if the local machine has an unreliable internet connection:

In[18]:=
CloudPut[Range[1000000], "MyData"];
Out[19]=

The result is only cached once it completes successfully:

In[20]:=
ResourceFunction["OnceUnlessFailed"][CloudGet["MyData"]] // AbsoluteTiming // Short
Out[20]=
In[21]:=
ResourceFunction["OnceUnlessFailed"][CloudGet["MyData"]] // AbsoluteTiming // Short
Out[21]=

Properties and Relations (1) 

Values for OnceUnlessFailed can be Unset just like Once:

In[22]:=
ResourceFunction["OnceUnlessFailed"][RandomReal[]]
Out[22]=
In[23]:=
ResourceFunction["OnceUnlessFailed"][RandomReal[]] =.
In[24]:=
ResourceFunction["OnceUnlessFailed"][RandomReal[]]
Out[24]=

Possible Issues (2) 

OnceUnlessFailed shares cache locations with Once:

In[25]:=
ResourceFunction["OnceUnlessFailed"][RandomReal[]]
Out[25]=
In[26]:=
Once[RandomReal[]]
Out[26]=

Using Unset on one will unset the other as well:

In[27]:=
Once[RandomReal[]] =.
In[28]:=
ResourceFunction["OnceUnlessFailed"][RandomReal[]]
Out[28]=

Requirements

Wolfram Language 11.3 (March 2018) or above

Version History

  • 1.0.0 – 15 August 2018

Related Resources

License Information