I want to write a custom sow/reap pair to wrap any piece of code in sow[code] and call reap to collect the timing of code with a tag that is the completely unevaluated version of code. My proble is that I cannot effectively withhold argument value substitution. I expect to use this pair only on my own functions fun so I can freely get and set DownValues as I like. Of course I expect to put many sow in my definition of fun. See example:
ClearAll[sow, reap, fun]; Attributes[reap] = {HoldAllComplete}; reap[x_] := Module[{h = (Hold@x)[[1, 0]], old, new, res}, old = DownValues[Evaluate@h]; (* store old DownValues *) new = old /. {sow[y_] :> Block[{time, out}, {time, out} = AbsoluteTiming@y; Sow[ToString@Unevaluated@y -> time]; out]}; DownValues[Evaluate@h] = new;(* install new DownValues *) res = Reap@x; DownValues[Evaluate@h] = old;(* restore old DownValues *) res]; fun[i_Integer] := sow@(Print["CALLED"]; Table[None, {i}]); Now call reap on fun:
In[1]:= reap[fun[2]] During evaluation of In[1]:= CALLED Out[1]= {{None, None}, {{"Print[CALLED]; Table[None, {2}]" -> 0.0000418147}}} This is almost what I want, but not exactly. How can I keep i from evaluating to the argument value 2? That is, I want to have "Print[CALLED]; Table[None, {i}]" instead of "Print[CALLED]; Table[None, {2}]" in the resulting tag. I guess this cannot be solved locally within any definition of sow, hence the DownValue-manipulation within reap. Can it be solved with the injector pattern or the Trott-Strzebonski in-place evaluation?
I know that I can specify tags manually in Sow but I specifically want to avoid this and simply use sow as a one-argument function.