I never used Asserts in Mathematica, but trying to see what advantage they have over just argument check and additional definitions of the function to capture unwanted input.
For example, which one of these 2 would you think is better?
ClearAll[f]
f[x_] := (Assert[x > 0]; Sqrt[x])
On[Assert];
f[2.]
f[-2.]
The last call above generated in the console a beep and a message:
Assert::asrtf: Assertion -2.>0 failed. >>
But I could also just write
ClearAll[f];
f[x_] := Sqrt[x] /; x > 0
f[2.]
f[-2.]
and the second call will return unevaluated
f[-2.]
and If I want a beep, I could always do something like
ClearAll[f];
f[x_] := Sqrt[x] /; x > 0
f[x_] := Throw["f[x] not supported for negative values"]
or something along these lines.
Since asserts seem to be used to assert that input to a function is within the ranges supported by the function, what benefit they have over the other method shown above?
Or should one look into using Asserts inside the function itself, i.e. in the middle of a computation, to check that intermediate results are within expected ranges? But also then, I would use a simple If
check instead, and return an error code to the caller (which I prefer) or use Throw. An example from help shows this:
myFun[x_] :=
Block[{y},
y = x^2;
Assert[y > 5];
Sin[y]
]
So that the call On[Assert]; myFun[1.0]
generated Assert::asrtf: Assertion y>5 failed
.
But I can write instead
myFun[x_] :=
Block[{y},
y = x^2;
If[y <= 5, Throw["y<=5"]];
Sin[y]
]
and now the call myFun[1.0]
will also generate a message and a beep as well from the same place.
I guess I am looking for when in Mathematica the use of Assert would be better and recommended over these other ways of checking.
My only guess now is that Assertion code can be disabled and enabled more easily, and this can have an effect on run time. i.e. after testing the code, I can disable Asserts from the final version, and it should run faster, since all these checks are not being done at run time any more. But with the manual checking as above, that code remains there all the time.
thanks
f
is an internal function, and my intention is never to call it with negative arguments, I'll putAssert[x>=0]
at the beginning. I might make a mistake somewhere which causesf
to be called with a negative argument anyway. This will be caught by the assertion. Once the program is debugged, I can disable assertions so there's no overhead from them. $\endgroup$f
is a public function that the users of my package call, then I have no control over what they pass to it. I need a permanent check I'll never turn off and I won't useAssert
. I will try to make sure that the checks I include are not too slow because they won't be turned off. WithAssert
performance is not really an issue because it'll be turned off eventually anyway, so, at least when writing C, I'll sprinkle the code with plenty of assertions. They are merely means to catch and find my own mistakes more easily. $\endgroup$