Function Repository Resource:

FailIfUnevaluated

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 non-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 (4) 

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]=

The action of the Listable and Flat attributes is considered non-trivial, even if the original head does not evaluate afterwards:

In[23]:=
Sin[{0, 1, x}]
Out[23]=
In[24]:=
ResourceFunction["FailIfUnevaluated"][Sin[{0, 1, x}]]
Out[24]=
In[25]:=
ClearAll[f];
SetAttributes[f, Flat]
In[26]:=
f[f[1]]
Out[26]=
In[27]:=
ResourceFunction["FailIfUnevaluated"][f[f[1]]]
Out[27]=

When the Orderless attribute sorts the arguments, this is counted as a trivial evaluation:

In[28]:=
y + x
Out[28]=
In[29]:=
ResourceFunction["FailIfUnevaluated"][y + x]
Out[29]=

Applications (3) 

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

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

This can be easily detected by FailIfUnevaluated:

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

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[34]:=
x || y
Out[34]=
In[35]:=
ResourceFunction["FailIfUnevaluated"][x || y]
Out[35]=
In[36]:=
x || y || False
Out[36]=
In[37]:=
ResourceFunction["FailIfUnevaluated"][x || y || False]
Out[37]=

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

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

Detect this with FailIfUnevaluated:

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

Possible Issues (2) 

Constant values and inert wrappers like List don't evaluate and thus return a failure:

In[42]:=
ResourceFunction["FailIfUnevaluated"][1]
Out[42]=
In[43]:=
ResourceFunction["FailIfUnevaluated"]["string"]
Out[43]=
In[44]:=
ResourceFunction["FailIfUnevaluated"][{1, 2, 3}]
Out[44]=

However, some Wolfram expressions evaluate even when it's not immediately visible:

In[45]:=
ResourceFunction["FailIfUnevaluated"][1/2]
Out[45]=

The FullForm demonstrates the difference:

In[46]:=
FullForm[Hold[1/2]]
Out[46]=
In[47]:=
FullForm[1/2]
Out[47]=

Associations evaluate when constructed, which is considered to be a non-trivial step. Because of this, they behave differently from a list of rules:

In[48]:=
ResourceFunction["FailIfUnevaluated"][<|"a" -> 1|>]
Out[48]=
In[49]:=
ResourceFunction["FailIfUnevaluated"][{"a" -> 1}]
Out[49]=

The difference can be seen when wrapping an Association with Hold:

In[50]:=
{Hold[<|"a" -> 1|>], <|"a" -> 1|>}
Out[50]=

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