Unexpected behavior with Derivative and a function parameters defined via an Association

I am confused by the following behavior:

ClearAll[u, i, x, y, func, z];
u = <|1 -> 1, 2 -> 2|>;
func[x_, i_, y_] := x u[i] + y u[i] + z[i][y];
Derivative[0, 0, 1][func][x, 2, y]


I expect the derivative to be u[2]+z[2]'[y] and since u[2] is 2 here that should be 2 + z[2]'[y]

Why is the result

Missing["KeyAbsent", 2] + Derivative[1][z[2]][y]


The final term makes perfect sense, but why the "KeyAbsent" message?

• Try D[func[x, 2, y], y] which gives 2 + z[2]'[y] Commented Oct 31, 2021 at 18:12
• Thanks Nasser, sadly this proves complicated too because x here is a function of y and I just want the partial evaluated at x[y] not the partial of func[x[y],i,y]. I could get around that with D[func[x,2,y],y]/.x->x[y], but the expressions are complicated and I hope to avoid all that. Hence my use of Derivative. Much appreciated though. Commented Nov 1, 2021 at 19:53

1 Answer

Why is the result

Missing["KeyAbsent", 2] + Derivative[1][z[2]][y]


Heads are evaluated first. The head of Derivative[0, 0, 1][func][x, 2, y] is Derivative[0, 0, 1][func], which yields the following:

Derivative[0, 0, 1][func]
(*  Missing["KeyAbsent", #2] + Derivative[1][z[#2]][#3] &  *)


This shouldn't be completely surprising because argument i has not yet been given a value. The way Mathematica computes Derivative[0, 0, 1][func] is to compute the derivative of func at private dummy variables, which I'll abbreviate as follows:

func[X[1], X[2], X[3]]
(*
Missing["KeyAbsent", X[2]] X[1] + Missing["KeyAbsent", X[2]] X[3] +
z[X[2]][X[3]]
*)


This is differentiated with respect to X[3] in this case. Then the dummy variables X[..] are replaced with Slot[..] (#2 etc.) as shown above. Finally the arguments x, 2, y are injected into the correspond slots.

The problem that Mathematica is addressing is that the derivative with respect to some variable(s) cannot be computed if you first replace the variables by some values. Clearest example: In Derivative[1,2,3][f][5,7,9], we cannot find the derivative of f after we plug in the constants 5,7,9.

Hence @Nasser's solution is the way to go.

Another approach is to use subvalues to protect nondifferentiable parameters from being differentiated:

ClearAll[u, i, x, y, func, z];
u = <|1 -> 1, 2 -> 2|>;
func[i_Integer][x_, y_] := x u[i] + y u[i] + z[i][y];
Derivative[0, 1][func[2]][x, y]
(*  2 + Derivative[1][z[2]][y]  *)

• Brilliant and clear as always, Michael. Makes perfect sense. I ultimately simply replaced the u as an associate with u defined via rules, e.g., params = {u[1]->1, u[2]->2} and apply the rules to the result of Derivative. I manage other parameters in the function definition that way so it doesn't add much overhead. But your clear explanation certainly helps me understand why it's necessary. Thanks! Commented Nov 1, 2021 at 19:57