I am trying a problem that should be simple: to create a function that contains a derivative. I need to do a more complex example, but even with the simplest I'm having trouble:

Let's consider

d[psi_[a_, b_, c_]] := D[psi, a] + D[psi, b]
p[x_, y_, z_] := x + y;
d[p[x, y, z]]

If I do that i receive the follow answer:

d[x + y]

I am only receiving a generic answer. Sometimes, I don't know why, I receive the evaluated answer (rarely).

Do you know what is wrong? I'm using Mathematica 9.


How do I have to modify the definitions above if I want to apply d to a list of functions?


1 Answer 1


Perhaps the closest to what you want is to set the HoldAll attribute on the function d. This way, it won't evaluate the argument p[x,y,z] at the time it is called, so that the pattern starting with psi in your definition can be matched.

I also had to add the arguments of psi to the body of d where the derivatives are being performed:


d[psi_[a_, b_, c_]] := D[psi[a, b, c], a] + D[psi[a, b, c], b]

SetAttributes[d, HoldAll]

p[x_, y_, z_] := x + 4 y^2;

d[p[x, y, z]]

(* ==> 1 + 8 y *)

I changed your definition of p to show that the derivatives are really done correctly now.

The reason why your definition didn't work initially is mainly because of the fact that p[x,y,z] was evaluated to x+y and only then was the result passed to the function d. The latter therefore saw x + y instead of the pattern [psi_[a_, b_, c_], and no action was taken.


In response to the additional question about differentiating two functions simultaneously, you only have to change one line:

SetAttributes[d, {HoldAll, Listable}]

With this, it's possible to call the d function with a list of functions. The pattern in the definition of d doesn't have to be modified at all:

d[{p[x, y, z], p[x1, y1, z1]}]

(* ==> {1 + 8 y, 1 + 8 y1} *)

Edit 2: Without HoldAll

If the goal is to manipulate functions outside of the d argument list, too, then these functions have to be referred to by their name only, and should not be applied to any arguments themselves because that would cause them to evaluate. When that happens, you don't have the functions anymore.

So here is a new definition and an example of how to use it:


d[f_] := Function[{x, y, z}, 
  Derivative[1, 0, 0][f][x, y, z] + Derivative[0, 1, 0][f][x, y, z]]

SetAttributes[d, Listable];

p[x_, y_, z_] := x + 8 y^2;

d[p][x2, y2, z]

(* ==> 1 + 16 y2 *)

c = {p, p};

(*  ==> {Function[{x$, y$, z$}, 
      Derivative[1, 0, 0][p][x$, y$, z$] + 
   Derivative[0, 1, 0][p][x$, y$, z$]], 
     Function[{x$, y$, z$}, 
      Derivative[1, 0, 0][p][x$, y$, z$] + 
   Derivative[0, 1, 0][p][x$, y$, z$]]}

  {{x, y, z}, {x1, y1, z1}}

(* ==> 
 {1 + 16 y, 1 + 16 y1}

So the output of d is a Function which you can see explicitly in d[c]. To get the variables inserted when a list like c = {p, p} is used, you have to do something like MapThread, as shown.

  • $\begingroup$ Thank you, @Jens. I'd never think about it. $\endgroup$
    – Zhozer
    Commented May 31, 2013 at 23:17
  • $\begingroup$ I'm still having problem. Doing that is ok for me, but if I define c={p[x, y, z], p[x1, y1, z1]}, and try d[c] I receive as answer d[c]. $\endgroup$
    – Zhozer
    Commented Jun 1, 2013 at 0:20
  • $\begingroup$ Yes, that's because of the HoldAll attribute. If I had known that you want to do that, I would have suggested a totally different approach. As soon as you assign c, it will of course contain the evaluated forms of p, and there is nothing you can do about that. I may have time later to write an alternative answer based on passing functions to d in a different way. $\endgroup$
    – Jens
    Commented Jun 1, 2013 at 0:26
  • $\begingroup$ Thank you, @Jens. It's exactly what I was trying to do. I did also some tests to see what I can do in this approach. I didn't know about MapsThread, but it's nice. $\endgroup$
    – Zhozer
    Commented Jun 3, 2013 at 5:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.