Skip to main content

function construction - How to make the $ModuleNumber dynamic in a string


This code can run normally


st = ToString[Unevaluated[j = i^2; a + b; Thread[{{1}, {2, 3}}]], 
InputForm];
i = 0; loopBody =
StringReplace[st,

RegularExpression["^|(?<=;)"] :>
TemplateApply["Print[<*i*>];", i++]]

And this is my expected answer



"Print[1];j = i^2;Print[2]; a + b;Print[3]; Thread[{{1}, {2, 3}}]"



So I want to pack it into a custom function like


SetAttributes[AddPrint, HoldFirst]
AddPrint[loopBody_] :=

Module[{st = ToString[Unevaluated[loopBody], InputForm], i = 0},
StringReplace[st,
RegularExpression["^|(?<=;)"] :>
TemplateApply["Print[<*i*>];", i++]]]

Then I get


AddPrint[j = i^2; a + b; Thread[{{1}, {2, 3}}]]


"Print[i];j = i^2;Print[i]; a + b;Print[i]; Thread[{{1}, {2, 3}}]"




I think the culprit is that $ModuleNumber is changing all the same.Of course we can make it like


SetAttributes[AddPrint, HoldFirst]
AddPrint[loopBody_] :=
Module[{st = ToString[Unevaluated[loopBody], InputForm]}, i = 0;
StringReplace[st,
RegularExpression["^|(?<=;)"] :>
TemplateApply["Print[<*i*>];", i++]]]

But I don't like this solution.I will make i be global.So I want to verify any smart way can do this?




Answer



You can replace your TemplateApply with either


TemplateApply["Print[``];", i++]

or


StringJoin["Print[", ToString[i++], "];"]

There is also a quick fix that is not recommended, which is to replace Module by Block.


Comments