Reputation: 3672
I want to write a function, mydiff
, that has a single argument, a 2-arg function, and computes the partial derivative w.r.t. to the first argument. Something like:
mydiff(f) := lambda([x, y], diff(f(x, y), x))
But, diff
needs to be run when mydiff
is called, not when it's defined (we don't have the definition of f
at that point), or when lambda
body is being executed (x
may have been replaced by a constant or complex expression at that point).
Specifically, how can I fill in the definition of mydiff
below?
mydiff(f) := ...;
myf(a, b) := a^2*b;
mydiff(myf)(3, 7);
Gives the answer 2*3*7
= 42
.
Upvotes: 0
Views: 204
Reputation: 17576
How about this.
mydiff (f) :=
block ([defn, vars, body],
defn: apply (fundef, [f]),
vars: args (lhs (defn)),
body: rhs (defn),
makelist (diff (body, vv), vv, vars),
apply (lambda, [vars, %%]));
fundef
retrieves the function definition like f(x) := ...
. Get the list of variables as the arguments of the left-hand side of the definition (i.e., f(x)
for example) and the body as the right-hand side (i.e., the ...
stuff). Make a list by differentiating the body wrt each variable. Finally, package the result as a lambda
expression which takes the same variables as arguments. Note that %%
is the preceding value in a sequence of expressions (i.e. in block
or (...)
).
You'll note the use of apply
to ensure that arguments are evaluated for fundef
and lambda
. In the interest of brevity I'll omit the explanation for now.
Here's what I get with that definition.
(%i44) myf(a, b) := a^2*b;
2
(%o44) myf(a, b) := a b
(%i45) mydiff(myf);
2
(%o45) lambda([a, b], [2 a b, a ])
(%i46) mydiff(myf)(3, 7);
(%o46) [42, 9]
Upvotes: 4