# Extract function argument sequence

Is it somehow possible to access and reference the sequence of arguments of a non-pure function?

For example if I want to take the derivative with respect to the n'th argument, a pseudocode example would be:

DiffNthArg[fun_,n_]:=D[fun,(*code for nth argument*)]

DiffNthArg[f[x,y,z],3]
Out[]: D[f[x,y,z],z]


I read that the one can extract the sequence of the function arguments by the following code: f /. f[z__]:>z Therefore one could use the following:

DiffNthArg[fun_,n_]:=D[fun, fun /. g_[z__] :> List[z][[n]] ]


BUT: This only works on undefined functions. If I apply it to already defined functions, the applied pattern will be applied to the already evaluated function, and thus does not return the list of function arguments.

For example, if I previously define f the following way, DiffNthArg will take the derivative with respect to c, not z:

f[x_,y_,z_]:= a b c z
DiffNthArg[f,3]
Out[]: a b z


How do I get the "original" argument sequence of the unevaluated function (even if it is already defined before)?

• You probably want to add some form of Hold attribute to the definition of your function. It may be helpful to add a specific example. Sep 1, 2021 at 17:07
• I thought, I added two examples already (one how it should behave and one how it actually behaves). The problem is, that once defined, f will be substituted by its defined expression (a b c z) no matter which kind of Hold I wrap around it. Sep 1, 2021 at 18:24

g[a_,b_,c_]:= a b c + 2 a + 1

(* the [[1, 1]] gets the signature of f,
while the [[All, 1]] gets the symbol from the list of Pattern-s *)
argList[f_] :=
ReleaseHold[DownValues[f][[1, 1]] /. {f -> List}][[All, 1]]

argList[g]
(** {a, b, c} **)

D[ g[a,b,c], argList[g][[3]] ]
(** a b **)

• Brilliant, this works as intended! For some reason I thought there might be a more direct way of accessing function arguments which I just couldn't find in the documentation. But this way is just as fine as well. Sep 2, 2021 at 11:19
• Ok, so there is one more question I have: Upon implementation, I realized that I could for example not do DFirst[f_] := D[f, argList[f][[1]]]. So if I define g[x,y]:=x+y, I would get DFirst[g[x,y]] --> 0. Why is that? Because argList needs as argument g but not g[x,y]. So when calling DFirst, instead of g being passed, x+y is passed to argList. Is there a way around that? Sep 3, 2021 at 19:09
• @jabberwocky g[x,y] is the result of applying g to x,y, so what you're asking doesn't make much sense. You should do DFirst[g] instead. Also define g[x_, y_] := x + y not g[x,y]:=x+y - otherwise you'd need to change argList to argList[f_]:=ReleaseHold[DownValues[f][[1, 1]] /. f -> List] if not using patterns (x_, y_) Sep 3, 2021 at 22:58
• Ah I see, that makes sense. So writing DFirst[f_] := D[f[argList[f] /. List -> Sequence], argList[f][[1]]] will work as expected. Thanks for the clarification! Sep 4, 2021 at 14:14