Wolfram Research

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:
ExpirationDate None when the cache should expire
PersistenceTime None how 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

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

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

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

PersistenceTime

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

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

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

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

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

Resource History

See Also

License Information