Trivial Case
I have a function doAnythingWith[expr_] that uses the expression expr for whatever.
(In fact, I use it to define a function with dynamic name, arguments and body. See https://community.wolfram.com/groups/-/m/t/2218132 and at the end of the attached notebook at "My actual need". At the moment this is not relevant here).
ClearAll[doAnythingWith];
doAnythingWith[expr_] :=
Print["doAnythingWith: ", expr // InputForm, "\t", expr];
I call this function from somewhere with a simple expression. This works, of course:
Block[{x, y, expr},
expr = x/y;
Print["Caller: ", expr // InputForm, "\t", expr];
doAnythingWith[expr]
]
Caller: x/y x/y
doAnythingWith: x/y x/y
Non - trivial Case
But as soon as I use a more complex expression, it becomes difficult. I want to pass expr as is as a conditional expression If[ !TrueQ[y==0], x/y, Indeterminate] but with y replaced:
Block[{x, y, expr},
Do[
If[NumericQ[do], y = do, Clear[y]];
expr = If[! TrueQ[y == 0], x/y, Indeterminate];
Print["Caller with y = ", y, ": ", expr // InputForm, "\t", expr];
doAnythingWith[expr];
, {do, {y, 2, 0}}]
]
Caller with y = y: x/y x/y
doAnythingWith: x/y x/y
Caller with y = 2: x/2 x/2
doAnythingWith: x/2 x/2
Caller with y = 0: Indeterminate Indeterminate
doAnythingWith: Indeterminate Indeterminate*
Of course, expr is now already evaluated in the caller and not passed to the function as desired.
I tried to avoid the evaluation in the caller and then within doAnyThingWith by using Hold, Unevaluated, Inactivate and various function definitions that reverse this and/or use the HoldAll attribute. But I did not succeed.
Some of the problems are avoided by passing the expression as a string. It now arrives correctly in the function, but is evaluated there by ToExpression and is therefore again not available:
ClearAll[doAnythingWithStr];
doAnythingWithStr[exprStr_String] :=
With[{expr = ToExpression[exprStr, InputForm]},
Echo[{exprStr // InputForm}, "doAnythingWithStr.exprStr: "];
Print["doAnythingWith: ", expr // InputForm, "\t", expr]
];
Block[{x, y, exprStr},
Do[
If[NumericQ[do], y = do, Clear[y]];
exprStr = "If[!TrueQ[y==0], x/y, Indeterminate]";
Print["Caller with y = ", y, ": ", exprStr // InputForm, "\t",
ToExpression[exprStr, InputForm]];
doAnythingWithStr[exprStr];
, {do, {y, 2, 0}}]
]
Caller with y = y: "If[!TrueQ[y==0], x/y, Indeterminate]" x/y
doAnythingWithStr.exprStr: {"If[!TrueQ[y==0], x/y, Indeterminate]"}
doAnythingWith: x/y x/y
Caller with y = 2: "If[!TrueQ[y==0], x/y, Indeterminate]" x/2
doAnythingWithStr.exprStr: {"If[!TrueQ[y==0], x/y, Indeterminate]"}
doAnythingWith: x/2 x/2
Caller with y = 0: "If[!TrueQ[y==0], x/y, Indeterminate]" Indeterminate
doAnythingWithStr.exprStr: {"If[!TrueQ[y==0], x/y, Indeterminate]"}
doAnythingWith: Indeterminate Indeterminate
And even if it remained correct we would have the problem that a possibly globally defined value for x would be replaced immediately. So you would have to pass, save, clear and restore the variables {x, y} of the expression as well.
Does anyone have an idea how to solve this behavior?
The attached notebook shows my actual need.
Attachments: