# How to deal with bad arguments when a function's UpValues is a pure-function?

In practice, I needs to define the UpValues of a user-defined function. For instance, the operation of function like differential formula , expansion and so on.

Here, I will give a example that came from my answer. Please see here

Bernstein::invidx =
"Index 1 should be a non-negative machine-sized integer betwwen 2 and 3.";

SyntaxInformation[Bernstein] = {"ArgumentsPattern" -> {_,_,_}};

SetAttributes[Bernstein, NumericFunction]
(*special cases*)
Bernstein[0, 0, u_?NumericQ] := 1
Bernstein[0, 0, u_Symbol] := 1

(*normal cases*)
Bernstein[deg_Integer?NonNegative, idx_Integer?NonNegative, u_?NumericQ] /;
idx <= deg && 0 <= u <= 1 :=
Binomial[deg, idx] u^idx (1 - u)^(deg - idx)

Bernstein[deg_Integer?NonNegative, idx_Integer?NonNegative, u_?NumericQ] /;
idx <= deg && (u > 1 || u < 0) := 0


### Throw the error-informations

Bernstein[deg_Integer?NonNegative, idx_Integer?NonNegative, u_] /;
idx > deg && (Message[Bernstein::invidx, idx, 0, deg - 1]; False) := $Failed; expr : Bernstein[deg_ /; ! (IntegerQ[deg] && NonNegative[deg]), idx_, u_] /; (Message[Bernstein::intnm, Unevaluated[expr], 1]; False) :=$Failed;

expr : Bernstein[deg_, idx_ /; ! (IntegerQ[idx] && NonNegative[idx]), u_] /;
(Message[Bernstein::intnm, Unevaluated[expr], 2]; False) := $Failed; Bernstein[args___] /; ! ArgumentCountQ[Bernstein, Length[{args}], 3, 3] && False :=$Failed;


The derivatives of Bernstein basis

Bernstein /: Derivative[0, 0, k_Integer?Positive][Bernstein] :=
Function[{deg, idx, u},
D[
deg (Bernstein[deg - 1, idx - 1, u] - Bernstein[deg - 1, idx, u]),
{u, k - 1}]
]


### TEST

D[Bernstein[3, -2, x], x]
D[Bernstein[3, -2, x], {x, 2}]


• How to deal with bad arguments when a function's UpValues is a pure-function? Namely, throw the error information and then return the symbol $Failed. Although Mr.Wizard given me a solution that using If[] func /: Derivative[0, 0, 1][func] := Function[{n, i, x}, If[MatchQ[n, _Integer?NonNegative] && MatchQ[i, _Integer?NonNegative] && i <= n, n (func[n - 1, i - 1, x] - func[n - 1, i, x]), Defer@func[n, i, x] ] ]  However, which leads to another issue. In fact, the built-in BSplineBasis[] also ingnore this problem. knots = {0, 0, 0, 0, 1/3, 2/3, 1, 1, 1, 1}; D[BSplineBasis[{3, knots}, 7, x], {x, 2}]  • Somewhat related: (8558). – Mr.Wizard Jan 18 '16 at 1:14 • I updated my answer with two minor changes that appear to address your new example. Please let me know if and where this fails; I did not try to be exhaustive. – Mr.Wizard Jan 21 '16 at 18:40 ## 1 Answer This references a past dialog on the subject of argument testing. There may be a good reasons for the side-effect method you are using, but in this case a check function may simplify things. func::invidx = "Index 1 should be a non-negative machine-sized integer betwwen 2 and 3."; func::intnm = "Number 1 should be a non-negative machine-sized integer."; ClearAll[nni, less, check] SetAttributes[check, HoldFirst] nni[n_Integer?NonNegative] := True nni[else_] := Message[func::intnm, else] less[i_, n_] /; i <= n || Message[func::invidx, i, 0, n] := True check[_[n_?nni, i_?nni, x_]] /; less[i, n] := NumericQ[x] check[_[args___]] /; ! ArgumentCountQ[func, Length[{args}], 3, 3] && False :=$Failed;
check[else_] := False


And now the main definitions:

func[a___]?check := #2/#1*#3 &[a]

func /: Derivative[0, 0, 1][func] := {n, i, x} \[Function]
If[Quiet @ check @ Hold[n, i, x],
n (func[n - 1, i - 1, x] - func[n - 1, i, x]),
Quiet @ func[n, i, x]
]


Now messages are as shown in your example but:

D[func[-4, 2, x], x]


func::intnm: Number -4 should be a non-negative machine-sized integer. >>

func[-4, 2, x]

D[func[-4, 2, x], {x, 2}]


func::intnm: Number -4 should be a non-negative machine-sized integer. >>

func[-4, 2, x]


I think this is the result you want?

• Thanks for your answer. I have a question: why D[func[-4, 2, x], x] throws many error infos func::intnm:, rather than just a func::intnm:? – xyz Jan 18 '16 at 1:44
• @Shutao One of them comes from the last term in If, which could be avoided with Defer. A Trace should show where the others originate; I think I'll do that now. – Mr.Wizard Jan 18 '16 at 1:47
• @Shutao The other leak came from check @ Hold[n, i, x] which I somehow forgot about. I'll update this answer to give only a single message in that call. – Mr.Wizard Jan 18 '16 at 1:51
• @Shutao Other than that, now fixed I hope, do you see any other problems in using this? – Mr.Wizard Jan 18 '16 at 1:54
• @Shutao Oh, I just realized that the check[_[args___]] /; ! ArgumentCountQ line isn't doing anything as check is only applied to the three-argument form. I'll fix that too. – Mr.Wizard Jan 18 '16 at 1:57