12
$\begingroup$

I'm working on a package that has functions that call other existing and packaged functions. I'd like a way to output what some of those key calls are, so users can see what's happening under the hood and for debugging purposes.

Here's a minimal example that wraps around NDSolve:

ex[eqns_, unks_, tmax_] := (
  Print["NDSolve[", eqns, ", ", unks, ", {t, 0, ", tmax, "}]"]; (* output code *)
  NDSolve[eqns, unks, {t, 0, tmax}]
)

ex[{n'[t] == n[t] (1 - n[t]), n[0] == 0.01}, {n}, 10]

NDSolve[{n'[t]==(1-n[t]) n[t],n[0]==0.01}, {n}, {t, 0, 10}]

{{n->InterpolatingFunction[...]}}

This approach basically works but has two issues I'd like to fix:

Issue 1: The output code is ugly and a minor hassle to write correctly.

Issue 2: If you copy and paste the output cell, it comes out as

"NDSolve["{n'[t]==(1-n[t]) n[t],n[0]==0.01`}", "{n}", {t, 0, "10"}]"

which isn't executable. I'd want to get:

NDSolve[{n'[t]==(1-n[t]) n[t],n[0]==0.01}, {n}, {t, 0, 10}]

Any ideas on how to address either (or hopefully both) of these issues?

$\endgroup$
16
$\begingroup$

You could define a function similar to Echo with the difference that it won't evaluate its argument before printing.

SetAttributes[echo, HoldAll]

echo[expr_] := (CellPrint@
   ExpressionCell[Defer[expr], CellDingbat -> ">"];
   expr)

Then just put it in front of anything you want printed:

ex[eqns_, unks_, tmax_] := echo@NDSolve[eqns, unks, {t, 0, tmax}]

Let's try it:

ex[{n'[t] == n[t] (1 - n[t]), n[0] == 0.01}, {n}, 10]

Mathematica graphics

The output is copyable.


Print should work fine instead of CellPrint/ExpressionCell. I used CellPrint so I would be able to add a CellDingbat.


Caveat: If eqns, unks, etc. were not directly substituted (e.g. if they were Module or Block variables) then their name would be printed instead of their value. Use With to directly substitute any value you want to print. For example,

In[20]:= fun[] := Module[{x = 2},
  echo[x^2]
  ]

In[21]:= fun[]

> x$21572^2

Out[21]= 4

In[22]:= fun[] := Module[{x = 2},
  With[{x = x}, echo[x^2]]
  ]

In[23]:= fun[]

> 2^2

Out[23]= 4

If you want to turn off debugging, simply set ClearAll[echo]; echo[x_] := x.

$\endgroup$
  • 2
    $\begingroup$ ExpressionCell[ Defer[expr], "Input", CellDingbat -> ">"] will even be directly evaluatable. $\endgroup$ – Kuba Oct 30 '17 at 14:52
  • 1
    $\begingroup$ @Kuba Can you make it so that: 1. the echo output will be replaced when re-evaluating the input (GeneratedCell -> True did not help) 2. the output won't inherit the style (dingbat, colour) of the echo output if the input is re-evaluated $\endgroup$ – Szabolcs Oct 30 '17 at 14:57
  • $\begingroup$ CellAutoOverwrite -> True should do. About 2), didn't get it and have to go. Will check later. $\endgroup$ – Kuba Oct 30 '17 at 15:15
  • $\begingroup$ This is great, thanks! $\endgroup$ – Chris K Oct 30 '17 at 18:17
  • $\begingroup$ @Kuba CellAutoOverwrite -> True didn't seem to fix the issue Szabolcs raised, but not having direct evaluability isn't such a big deal. $\endgroup$ – Chris K Oct 30 '17 at 18:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.