I find it a really bad idea to re-define how D
calculates derivatives; I'm pretty sure that in the majority of use-cases I have encountered, it has never been a good idea to 'overload' D
in such a manner and I am stating this as a matter of personal fact.
It can conceivably be considered as an appropriate approach to pursue by really experienced users that know what they are doing but I definitely do not consider myself to be among their rank so I don't use it.
Having said that, a way around the issue of Unprotect
-ing built-in symbols in general and D
in particular might be defining a 'wrapper' function around the original built-in symbol.
Consider evaluating the following lines
ClearAll[d]
SetAttributes[d, HoldFirst]
d[f_[x_]] := D[f[x], x]
We're using HoldFirst
as a Attribute
for our derivative operator d
in order to not allow it to evaluate its input; this will come in handy later.
Symbol d
now can be used to calculate simple first degree derivatives eg evaluating
f[x_]:=x^2
d[f[x]]
will return
2x
as expected.
Now, in order to address the theme of 'changing the derivative of a function', consider again the example of f[x_]:=x^2
above but let's set its derivative equal to 3 x + 1
.
In order to accomplish this, we can evaluate the following
d[f[x_]] ^:= 3x+1
Note we are using UpSetDelayed
(see UpSetDelayed).
Also note that, had we not used HoldFirst
earlier in the attribute list of symbol d
, we would not have been be able to use UpSetDelayed
successfully; there would also be other unwanted side effects, such as the possibility that the definition of d
might not have been able to identify its input correctly and would thus return unevaluated.
As an educational aside, we can clear all definitions made so far and attempt to evaluate everything again, with the exception of not using HoldFirst
, this time. Doing that will produce two errors.
- evaluating
d[f[x]]
will return un-evaluated ie d[x^2]
- attempting to define our derivative operator will return an
UpSetDelayed::write
error message.
Issue no. 1 occurs because Mathematica evaluates f[x]
before applying any rules to it. Evaluating f[x]
produces x^2
and our new operator d
does not match any rule of the form d[Power[x, 2]]
hence it returns un-evaluated.
Issue no. 2 occurs because Power
is a built-in symbol and it is Protected
thus not allowing us to modify rules associated with it (that is partly the issue we are trying to avoid with defining the wrapper function d
for D
in the first place).
Returning from this brief detour, after clearing all definitions once more, and evaluating everything, including SetAttributes[f,HoldFirst]
, doing something like
d[f[x]]
would return
1+3x
as expected.
I include the notebook code as one unified piece for ease of replication
Code block 1
ClearAll[f, d]
SetAttributes[d, HoldFirst]
d[f_[x_]] := D[f[x], x]
f[x_] := x^2
d[f[x]]
d[f[x_]] ^:= 3 x + 1
d[f[x]]
Code block 2 (to replicate errors)
ClearAll[f, d]
d[f_[x_]] := D[f[x], x]
f[x_] := x^2
d[f[x]]
d[f[x_]] ^:= 3 x + 1
d[f[x]]
Unprotect
D
/Derivative
in order to overwrite pattern matching rules for built-in functions. That's becausea'[x]
actually evaluates toDerivative[1][a][x]
which means it belongs toDerivative
. $\endgroup$Unprotect[Derivative]; a[x_] := Sin[x]; Derivative[1][a][x_] := -Sin[x];
should work? It somehow does not for me. $\endgroup$