Function Repository Resource:

FailWhenUndefined

Source Notebook

Append a definition rule to a symbol so that it will fail when given undefined arguments

Contributed by: Richard Hennigan (Wolfram Research)

ResourceFunction["FailWhenUndefined"][f]

appends a rule to the definition of f so that it will return a Failure object rather than remain unevaluated for undefined arguments.

ResourceFunction["FailWhenUndefined"][f,handler]

applies handler to the generated Failure object at the time of failure.

ResourceFunction["FailWhenUndefined"][f,handler,type]

specifies which set of values to modify for f.

Details and Options

The default value for handler is Identity.
The default value for type is DownValues.
The value for type can be one of the following:
OwnValuesdefinitions of the form f:=
DownValuesdefinitions of the form f[]:=
SubValuesdefinitions of the form f[][]:=
{SubValues,n}definitions of the form f[][]:=
nequivalent to {SubValues,n}
ResourceFunction["FailWhenUndefined"] accepts the option "Message" which specifies whether a message should be issued at the time of failure.

Examples

Basic Examples (2) 

Define a function so that it fails when given undefined arguments:

In[1]:=
AddOne[x_?NumberQ] := x + 1;
ResourceFunction["FailWhenUndefined"][AddOne];

Check the definition:

In[2]:=
Definition[AddOne]
Out[2]=

Defined behavior:

In[3]:=
AddOne[5]
Out[3]=

Undefined behavior:

In[4]:=
AddOne["test"]
Out[4]=
In[5]:=
AddOne[1, 2, 3]
Out[5]=

Specify a function to apply to the failure object at the time of failure:

In[6]:=
AddTwo[x_?NumberQ] := x + 2;
ResourceFunction["FailWhenUndefined"][AddTwo, Throw]
Out[7]=

Defined behavior:

In[8]:=
Catch[AddTwo /@ {1, 2, 3}]
Out[8]=

Undefined behavior:

In[9]:=
Catch[AddTwo /@ {1, 2, "three"}]
Out[9]=

Scope (4) 

Catch undefined SubValues:

In[10]:=
Add2[x_?NumberQ][y_?NumberQ] := x + y;
ResourceFunction["FailWhenUndefined"][Add2, Identity, SubValues];

This allows undefined operator forms:

In[11]:=
Add2[5]
Out[11]=
In[12]:=
Add2[5][6]
Out[12]=

Undefined behavior is caught when applying the operator form:

In[13]:=
Add2["hello"]
Out[13]=
In[14]:=
Add2["hello"]["world"]
Out[14]=

Specify the number of SubValues positions:

In[15]:=
Add3[x_?NumberQ][y_?NumberQ][z_?NumberQ] := x + y + z;
ResourceFunction["FailWhenUndefined"][Add3, Identity, {SubValues, 3}];
In[16]:=
Add3[5][6][7]
Out[16]=
In[17]:=
Add3[5][6]["hello"]
Out[17]=

Fail for undefined OwnValues:

In[18]:=
$value /; $condition := "The condition is True";
$value /; ! $condition := "The condition is False";
ResourceFunction["FailWhenUndefined"][$value, Identity, OwnValues];

Defined behavior:

In[19]:=
$condition = True;
$value
Out[13]=
In[20]:=
$condition = False;
$value
Out[21]=

Undefined behavior:

In[22]:=
$condition = "hello";
$value
Out[23]=

Use an integer as shorthand for {SubValues,n}:

In[24]:=
ResourceFunction["FailWhenUndefined"][symbol, Identity, 3];
Definition[symbol]
Out[25]=

Options (1) 

Message (1) 

Do not issue a message when failing:

In[26]:=
MyFunction[x_] := x + 1;
ResourceFunction["FailWhenUndefined"][MyFunction, "Message" -> False];
In[27]:=
Definition[MyFunction]
Out[27]=
In[28]:=
MyFunction[1, 2]
Out[28]=

Properties and Relations (3) 

One level of SubValues is equivalent to DownValues:

In[29]:=
ResourceFunction["FailWhenUndefined"][MyFunction1, Identity, {SubValues, 1}];
Definition[MyFunction1]
Out[30]=

Zero levels of SubValues is equivalent to OwnValues:

In[31]:=
ResourceFunction["FailWhenUndefined"][MyFunction0, Identity, {SubValues, 0}];
Definition[MyFunction0]
Out[32]=

FailWhenUndefined always appends definitions so that it will not rewrite existing ones:

In[33]:=
ClearAll[MyFunction];
MyFunction[x_] := x + 1;
expr$ : HoldPattern[MyFunction[___]] := Failure["MyFailure", <|"Expression" :> expr$|>];
ResourceFunction["FailWhenUndefined"][MyFunction];
In[34]:=
Definition[MyFunction]
Out[34]=

In this case, the definition created by FailWhenUndefined is unreachable:

In[35]:=
MyFunction[1, 2]
Out[35]=

Possible Issues (4) 

Definitions created by FailWhenUndefined may be overwritten by other definitions, so it should be used after all other definitions have been created for a symbol in order to avoid unexpected results:

In[36]:=
ClearAll[MyFunction];
ResourceFunction["FailWhenUndefined"][MyFunction];
MyFunction[x___] := x + 1;
In[37]:=
Definition[MyFunction]
Out[37]=

Always apply FailWhenUndefined last:

In[38]:=
ClearAll[MyFunction];
MyFunction[x___] := x + 1;
ResourceFunction["FailWhenUndefined"][MyFunction];
In[39]:=
Definition[MyFunction]
Out[39]=

FailWhenUndefined defines a message for the given symbol:

In[40]:=
ClearAll[MyFunction];
ResourceFunction["FailWhenUndefined"][MyFunction];
In[41]:=
Messages[MyFunction]
Out[41]=
In[42]:=
MyFunction[1, 2, 3]
Out[42]=

If the "undefined" message tag already exists for the given symbol, FailWhenUndefined will be used instead:

In[43]:=
ClearAll[MyFunction];
MyFunction::undefined = "My custom message";
ResourceFunction["FailWhenUndefined"][MyFunction];
In[44]:=
MyFunction[1, 2, 3]
Out[44]=

The original message is unmodified:

In[45]:=
Messages[MyFunction]
Out[45]=

Repeated applications of FailWhenUndefined will add unreachable definition rules:

In[46]:=
ClearAll[MyFunction];
ResourceFunction["FailWhenUndefined"][MyFunction];
ResourceFunction["FailWhenUndefined"][MyFunction];
ResourceFunction["FailWhenUndefined"][MyFunction];
In[47]:=
Definition[MyFunction]
Out[47]=

Version History

  • 1.0.0 – 04 March 2022

Related Resources

License Information