I have a computationally intense function f
that returns a matrix. Sometimes only the diagonal is needed, which is faster to compute, thus there's a syntax for f to return only the diagonal, say f[...,Diagonal->True]
. I would like Diagonal[f[...]]
to evaluate to f[...,Diagonal->True]
.
Naive attempt at using UpValue
fails
f[x_] := x.Transpose[x];
Diagonal[f[x_]] ^:= f[x, Diagonal->True];
because f[...]
is evaluated first.
How can I achieve the desired behaviour? What would be the "Mathematica way" of handling this situation?
Update:
It appears that the requested behaviour might not be implementable in Mathematica.
Related approaches proposed so far:
Hold argument to Diagonal:
Diagonal[Unevaluated@f[...]]
with UpValuesf /: Diagonal[f[x_]] := f[x, Diagonal -> True]
Works, but is more cumbersome than directly calling
f[..., Diagonal->True]
as one needs to remember usingUnevaluated
instead of an option tof
Replace
Diagonal
by a convenience functiondiagonal
, which works withHoldAllComplete
Works, but is more cumbersome than directly calling
f[..., Diagonal->True]
as one needs to remember using another functiondiagonal
instead of an option tof
Define only UpValues for
f
, so it is only evaluated if it has a surrounding contextWorks, but requires modifying
$Post
, which is as undesirable as modifying the built-inDiagonal
.
f /: Diagonal[f[x_]] := f[x, Diagonal -> True]
but it won't help because in standard evaluation sequence arguments ofDiagonal
will be evaluated before custom rules. (tutorial/Evaluation). Then you can useDiagonal[Unevaluated@f[{{a, b}, {c, d}}]]
but is that handy? $\endgroup$ – Kuba♦ Jul 13 '16 at 9:27f[..., Diagonal->True]
directly. ChangingDiagonal
viaUnprotect
to hold its argument is undesirable as well due to affecting other uses ofDiagonal
. $\endgroup$ – mrupp Jul 13 '16 at 9:48diagonalF
but maybe I'm missing something. $\endgroup$ – Kuba♦ Jul 13 '16 at 9:49