Function Repository Resource:

FailIfUnevaluated (1.0.0) current version: 1.0.1 »

Source Notebook

Test if a function doesn't evaluate for given arguments

Contributed by: Sjoerd Smit

ResourceFunction["FailIfUnevaluated"][sym]

returns the value of a symbol if it evaluates and returns $Failed otherwise.

ResourceFunction["FailIfUnevaluated"][head[args]]

returns the result of head[args] if the evaluation is not-trivial and $Failed otherwise.

ResourceFunction["FailIfUnevaluated"][expr, default]

returns default instead of $Failed.

Details

For composite expressions, ResourceFunction["FailIfUnevaluated"] will first evaluate head and then args in accordance with the Attributes associated with head. After that, the full expression is tested to see if it evaluates in a non-trivial way.
Any evaluation associated with just the head or just the arguments is considered to be trivial.
ResourceFunction["FailIfUnevaluated"] is intended as a robust way to detect when built-in functions like Solve fail by returning unevaluated.
ResourceFunction["FailIfUnevaluated"] has the attribute HoldAllComplete.

Examples

Basic Examples (2) 

Evaluate a symbol with a value:

In[1]:=
ResourceFunction["FailIfUnevaluated"][$VersionNumber]
Out[1]=

A symbol without value gives $Failed:

In[2]:=
ResourceFunction["FailIfUnevaluated"][x]
Out[2]=

This expression only evaluates in its arguments, the head f has no effect:

In[3]:=
f[1 + 1]
Out[3]=

FailIfUnevaluated detects this and considers this a trivial evaluation:

In[4]:=
ResourceFunction["FailIfUnevaluated"][f[1 + 1]]
Out[4]=

It does not simply test if the head remains the same. This is an example of a non-trivial evaluation that FailIfUnevaluated allows:

In[5]:=
f[x_] := f[x, x];
ResourceFunction["FailIfUnevaluated"][f[1 + 1]]
Out[6]=

Scope (3) 

If the head evaluates on its own but afterwards no further evaluation takes place, FailIfUnevaluated will give $Failed:

In[7]:=
ClearAll[f, g];
f = g;
In[8]:=
f[2 + 2]
Out[8]=

This fails because f is taken to be no more than a simple alias for g:

In[9]:=
ResourceFunction["FailIfUnevaluated"][f[2 + 2]]
Out[9]=

This will not fail:

In[10]:=
g[x_] := Sqrt[x];
f[2 + 2]
Out[11]=
In[12]:=
ResourceFunction["FailIfUnevaluated"][f[2 + 2]]
Out[12]=

However, if the whole expression transforms into another inert expression, this is still counted as a non-trivial evaluation:

In[13]:=
ClearAll[h, k];
h[x_] := k[x];
ResourceFunction["FailIfUnevaluated"][h[2 + 2]]
Out[15]=

Use a different default:

In[16]:=
ResourceFunction["FailIfUnevaluated"][x, Missing[]]
Out[16]=

The default does not evaluate if it's not needed:

In[17]:=
ResourceFunction["FailIfUnevaluated"][1 + 1, Print["Test"]]
Out[17]=

FailIfUnevaluated respects attributes of the head while testing for evaluation semantics:

In[18]:=
ClearAll[f];
SetAttributes[f, HoldFirst]
f[n_Integer] := n^2;

This expression evaluates:

In[19]:=
f[2]
Out[19]=
In[20]:=
ResourceFunction["FailIfUnevaluated"][f[2]]
Out[20]=

This expression doesn't evaluate because of the HoldFirst attribute, which causes FailIfUnevaluated to fail:

In[21]:=
f[1 + 1]
Out[21]=
In[22]:=
ResourceFunction["FailIfUnevaluated"][f[1 + 1]]
Out[22]=

Applications (3) 

Due to the symbolic nature of the language, many Wolfram Language functions stay unevaluated when given unsupported arguments:

In[23]:=
If[x < 1 + 1, "case 1", "case 2"]
Out[23]=
In[24]:=
Boole[x || False]
Out[24]=

This can be easily detected by FailIfUnevaluated:

In[25]:=
ResourceFunction["FailIfUnevaluated"]@
 If[x < 1 + 1, "case 1", "case 2"]
Out[25]=
In[26]:=
ResourceFunction["FailIfUnevaluated"][Boole[x || False]]
Out[26]=

Note that FailIfUnevaluated does not test for a specific return value. In the following examples, Or returns the same result, but the second example represents a partial evaluation which is considered non-trivial:

In[27]:=
x || y
Out[27]=
In[28]:=
ResourceFunction["FailIfUnevaluated"][x || y]
Out[28]=
In[29]:=
x || y || False
Out[29]=
In[30]:=
ResourceFunction["FailIfUnevaluated"][x || y || False]
Out[30]=

Symbolic math functions usually return unevaluated if they can't find a simpler result:

In[31]:=
Integrate[Exp[Sin[x]] + 3*6, x]
Out[31]=
In[32]:=
Reduce[Exp[x] + Array[c, 3] . x^Range[3] == 0, x]
Out[32]=

Detect this with FailIfUnevaluated:

In[33]:=
ResourceFunction["FailIfUnevaluated"]@Integrate[Exp[Sin[x]] + 3*6, x]
Out[33]=
In[34]:=
ResourceFunction["FailIfUnevaluated"]@
 Reduce[Exp[x] + Array[c, 3] . x^Range[3] == 0, x]
Out[34]=

Publisher

Sjoerd Smit

Requirements

Wolfram Language 13.0 (December 2021) or above

Version History

  • 1.0.1 – 27 October 2023
  • 1.0.0 – 25 October 2023

Related Resources

License Information