# An evaluation control problem

I want to have a function called printRes[expr_,var_], which does the following:

x=1;
expr:=a*x^3;

result=printRes[expr,x];
result
(* derivative of a*x^3 relative to x is 3ax^2, and when x=1, result is 3a. *)


I am unable to put all this into a row after many tries. How do I do it?

• Like StringTemplate["The derivative of fun with respect to var is res when var = val"]@<|"fun" -> ToString[f, TraditionalForm], "var" -> x, "val" -> 1, "res" -> ToString[D[f, x] /. x -> 1, TraditionalForm]|>? Dec 10, 2016 at 12:44
• Hi, @J.M. Thanks for mention StringTemplate, haven't used it before. But there is a problem, x=1 must be evaluated before evaluation of printRes Dec 10, 2016 at 12:50
• So, what did you see after running the snippet I gave? Note the expression fed to "res" in the association. Dec 10, 2016 at 12:53
• @J.M. Your solution seems not give the expected result. I have edited my post to make it more clear Dec 10, 2016 at 13:05
• Well, the trouble is that you assigned x to be 1 at the outset. Dec 10, 2016 at 13:08

## 2 Answers

Localize your x using Block. Use LocalizedBlock if you want to allow non-symbols for x.

ClearAll[printRes]
SetAttributes[printRes, HoldAll]
printRes[expr_, x_] :=
InternalLocalizedBlock[{x},
Print[D[expr, x]]
]


If you really want to both make use of the value of x and ignore it,

ClearAll[printRes]
SetAttributes[printRes, HoldAll]
printRes[expr_, x_] :=
Module[{res},
InternalLocalizedBlock[{x},
res = Hold[Evaluate@D[expr, x]];
];
{res, ReleaseHold[res]}
]


But I find a function with such behaviour weird and confusing.

• Thank you so much, Szabolcs! I just understand your answer, very neat and clear. upvoted Dec 10, 2016 at 15:29
• A complete solution would be like this : ClearAll[printRes]; SetAttributes[printRes, HoldAll]; printRes[expr_, x_] := Module[{expr0, res}, Block[{x}, expr0 = HoldForm@Evaluate@expr; res = HoldForm@Evaluate@D[expr, x];]; Row[{"derivative of ", expr0, " relative to ", HoldForm@x, " is ", res, ", and when ", HoldForm@x, " = ", x, ", result is ", ReleaseHold[res], "."}]] Dec 10, 2016 at 15:31

How about:

ClearAll@printRes;
SetAttributes[printRes, HoldAll]
With[{trad = TraditionalForm},
With[{hold = trad@HoldForm@# &},
printRes[expr_, y_] :=
"derivative of " <> #1 <> " relative to " <> #2 <> " is " <> #3 <>
", and when " <> #2 <> "=" <> #4 <> ", the result is " <> #5 & @@
ToString /@
Block[{y}, {hold@expr, hold@y, hold@D[expr, y], trad@y, trad@D[expr, y]}]]]

• Hi, xzczd. Thank you so much. It works! But I just found I missed something important in my post which may bring true difficulty. Take a look at my updated post again. Very sorry for my mistake. Dec 10, 2016 at 14:09
• @matheorem I found a cleaner solution, check my update. Dec 10, 2016 at 14:14
• upvoted! Thank you so much. It is weird that it is failed on my first try. But it seems great now. I need sometime to figure it out : ) Dec 10, 2016 at 14:25
• @matheorem Well, this solution has avoided most of the Hold* stuff, the key point is the Block. We first use Block to temporarily localize the variable so expr, D[expr, y], etc. will evaluate but not evaluate to a number, then use HoldForm to hold those should not evaluate even if they're no longer inside the Block. For more information, try printRes[expr, x] // Trace. Dec 10, 2016 at 14:46
• I think the truth is more tricky. You used hold=HoldForm@#& instead of hold=HoldForm makes an essential difference (neglect TraditionalForm) Dec 10, 2016 at 15:10