I believe there are at least three cases treated separately by Derivative
.
1) A function defined by a Symbol
.
This follows the the rule cited in the documentation.
g[x___] := f[x];
Derivative[1][g][x] // Trace
(*
{ { g'
, { g[#1] <-- Here the rule is being applied
, f[#1] }
, f'[#1] & }
, (f'[#1] &)[x]
, f'[x] }
*)
2) A function defined by Function
, with explicit symbolic arguments.
This one cannot mimic f[##] &
, but it seems to be a special case not handled in the way explained in the documentation; rather, the body is differentiated directly.
Derivative[1][Function[{x}, f[x]]][x] // Trace
(*
{ { Function[{x}, f[x]]'
, Function[{x}, f'[x]] } <-- Differentiates the body
, Function[{x}, f'[x]][x]
, f'[x]}
*)
3) A "pure" Function
(the OP's case).
This also is handled by direct differentiation of the body, with respect to Slot[1]
. In the OP's example, the expression does not (symbolically) depend on Slot[1]
, so its derivative is zero.
Apparently, rewriting SlotSequence
in terms of Slot
, say, in accord with the number of arguments passed to Derivative
was either rejected or not considered in the design of Derivative
.
Derivative[1][f[##] &][x] // Trace
(*
{ { (f[##1] &)'
, 0 & } <-- Differentiates the body
, (0 &)[x]
, 0}
*)
The following is equivalent to my view of how Derivative
works:
deriv[n__][f_] := f /. {
HoldPattern[Function[body_]] :>
With[{dbody = D[body, Sequence @@ Transpose@ {Array[Slot, Length@{n}], {n}}]},
Function[dbody]],
HoldPattern[Function[vars_List, body_]] /; Length[vars] == Length[{n}] :>
With[{dbody = D[body, Sequence @@ Transpose@ {vars, {n}}]},
Function[vars, dbody]],
HoldPattern[ff_] :>
With[{vars = Array[Slot, Length@{n}]},
Evaluate@ D[ff @@ vars, Sequence @@ Transpose@ {vars, {n}}] &]}
deriv[1][g][x]
deriv[1][Function[{x}, f[x]]][x]
deriv[1][f[##] &][x]
(*
Derivative[1][f][x]
Derivative[1][f][x]
0
*)