There are a few issues with your code. A minimal change to make it work would be:
ClearAll[J];
J[HoldPattern[Function[vars_List /; VectorQ[vars], funs_]]] :=
Function @@ Evaluate /@ {vars, D[funs, {vars}]}
The reason you need HoldPattern
has to do with how lhs. of assignment is evaluated during the assignments.
However, this is not all. The code as it stands has problems in the form of evaluation leaks, particularly when the variables have global values. A safer version of the code would be:
ClearAll[J];
J[HoldPattern[Function[vars_List /; VectorQ[Unevaluated[vars]], body_]]] :=
Block[vars, Function @@ {vars, D[body, {vars}]}]
where I used Unevaluated
to prevent evaluation of vars
during pattern-matching, Block
to prevent evaluation of vars
during function construction on the r.h.s., and removed Evaluate
, which isn't needed. Note also that, while I left your VectorQ
test for didactic purposes, it isn't needed either, because you already test that the arguments are in a list.
Personally I'd use yet different code:
ClearAll[J];
J[HoldPattern[Function[vars : {__Symbol}, body_]]] :=
Block[vars, Function @@ {vars, D[body, {vars}]}]
which is simpler and avoids some of the problems of the previous versions, while being yet more robust.