Mathematica: TIP: Protecting against computations breaking verbosely because of Null, None, Undefined. And about using Undefined as a return policy.

Webel IT Australia promotes the amazing Mathematica tool and the powerful Wolfram Language and offers professional Mathematica services for computational computing and data analysis. Our Mathematica tips, issue tracking, and wishlist is offered here most constructively to help improve the tool and language and support the Mathematica user community.
DISCLAIMER: Wolfram Research does not officially endorse analysis by Webel IT Australia.
Icon class
icon_class
far fa-sticky-note
icon_class_computed
far fa-sticky-note
Note kind
Policy level
Keywords
In a utility package define the following:

isDefNotNull[var_] := !(var===Null) && !(var===None) && !(var===Undefined);

isAllDefNotNull[vars_] := AllTrue[vars,isDefNotNull[#]&];
Then throughout your entire system cleanly test before computing; if the involved values are not defined (in the sense of the above test) return Undefined. For example:

mySafeFunction[x_,y_] := If[isAllDefNotNull[{x,y}],
    x+y,
    Undefined
];
For that simple example, if you did not test first, for x=1. and y=Null you'd just get the relatively harmless partially symbolic:

1.+Null
But for more complex calculations you'd end up with a complete mess. According the the returned strategy advocated here, the returned Undefined is used throughout an application to communicate that not all required information is available. This can be used to communicate progressive value via the user interface. You can even use special styling such as decorating returned Undefined in Orange.

In this example safe unit conversion is performed:


convertSafe[v_,unit_] := If[isDefNotNull[v], UnitConvert[v,unit], Undefined];
You can use the strategy to collect all arguments as a List and test them before passing them to a lower level function using Apply shorthand @@ like this:


service[x_,y_,z_] := ....

safeService[x_,y_,z_] := With[
   {args={x,y,z}},
   If[isAllDefNotNull[args],
     service@@args,
     Undefined
   ] 
]
Of course, if you are using an on-the-fly cascading derived value accessors you can do this:


derived[] := With[
   {args={x[],y[],z[]}},
   If[isAllDefNotNull[args],
     service@@args,
     Undefined
   ] 
]
Diagnostics about why a computation is Undefined can also be included, but that's beyond the scope of this tip.
Relates to
Related notes
Related notes (backlinks)
Related snippets (extracts)
Visit also
Visit also (backlinks)