I usually check my intermediate variable by Echo.Like

Table[Echo@x, {x, 10}]

But when the intermediate variable have too much value,the Font-End often crash,such as Table[Echo@x, {x, 10^3}].So I want to make a custom myEcho,which always show the first 5 results when I run Table[myEcho@x, {x, 10}] every time.Like

Table[myEcho@x, {x, 10}]

Or we can specify the times that we hope,such as Table[myEcho[x,3], {x, 10}] will show the first 3 results

As the Kuba's fix,this is current method.

Clear[fun, myEcho]
fun[n_: 5] := 
 Module[{times = 0}, (times++; If[times <= n, Echo, Identity][#]) &]

myEcho = fun[5];
Table[myEcho@x, {x, 10}]

But the weakness is obvious still,which mean I should run myEcho = fun[5];Table[myEcho@x, {x, 10}] every time.Actually I hope get a same result when I just run Table[myEcho@x, {x, 10}].


Here is how I would approach this:

Clear[myEcho, myEchoCounter]
myEcho::stop = "Further output from `` will be suppressed during evaluation of In[``].";
myEcho[, ] := myEcho[];
myEcho[label_: Null, max_: 3][expr_] /; myEchoCounter[$Line, label] >= max := expr
myEcho[label_: Null, max_: 3][expr_] := (
   If[Not@NumberQ[myEchoCounter[$Line, label]], myEchoCounter[$Line, label] = 0];
   If[myEchoCounter[$Line, label] < max, 
    If[MatchQ[label, Null | None], Echo[expr], Echo[expr, label]]];
   If[++myEchoCounter[$Line, label] == max, 
    Message[myEcho::stop, "myEcho"[label, max], $Line]];


(myEcho["Before Table"][x]; Table[myEcho["Table"][x], {x, 10}]; myEcho["After Table"][x])

(Table[myEcho[, 3][x], {x, 10}]; Table[myEcho[, 6][x], {x, 10}])


  • $\begingroup$ This is solution near to perfect,I will accept it after 36h if there is no better answer. $\endgroup$
    – yode
    Mar 23 '17 at 12:22
  • $\begingroup$ Just when we don't set any label or we set a same label,we cannot get the result we want,I don't sure whether $ModuleNumber can help or not. $\endgroup$
    – yode
    Mar 23 '17 at 12:52
  • 1
    $\begingroup$ @yode What you call "unexpected" is actually "by design": on the same $Line myEcho with the same label (or without a label) prints no more than max (by default 3) times. $\endgroup$ Mar 23 '17 at 12:56
  • $\begingroup$ So I just wonder we can add a $ModuleNumber after our label but we don't show that $** $\endgroup$
    – yode
    Mar 23 '17 at 13:03
  • 1
    $\begingroup$ Adding this code will automate the labelling process for Echo. $Pre =.; $Pre = Function[u, Module[{c = 0}, (Hold[u]) /. HoldPattern[Echo[a__]] :> RuleCondition[Inactive[myEcho][++c][a]]] // Activate // ReleaseHold, HoldAll]; $\endgroup$
    – vapor
    Mar 23 '17 at 13:10

Another way to do this:

In[1]:= << GeneralUtilities`

In[2]:= $MaximumEchoRate = 5;

In[3]:= Table[EchoHold@x, {x, 10}]

x \[Function] 1

x \[Function] 2

x \[Function] 3

x \[Function] 4

x \[Function] 5

During evaluation of In[3]:= Maximum echo rate exceeded, change $MaximumEchoRate to adjust.

Out[3]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
  • 2
    $\begingroup$ This is nice (+1), but it is a rate, and therefore time-dependent. It will echo no more than five times per second. $\endgroup$
    – Michael E2
    Mar 23 '17 at 14:27
  • 1
    $\begingroup$ Good dig,bug I find it will ignore the second Echo in this case. $\endgroup$
    – yode
    Mar 23 '17 at 23:05
crit = 2;
SetAttributes[MyEcho, HoldAll]
Module[{res},MyEcho[label_, return_, subexpr___] :=
  If[NumberQ[label],If[label >= crit, return,
    label++; res = Echo[return, subexpr];
    If[label == crit, Print["Already " <> ToString[crit] <> " Echo here!\nNo more Echo allowed!!!!"]];res],
  label = 1; Echo[return, subexpr]]]

$Pre = 
   Function[{expr}, ReleaseHold[Hold[expr] /. HoldPattern[Echo[subexpr__]] :> 
       With[{u = Unique[]}, MyEcho[u, subexpr] /; True]], HoldAll]

Similar results, but a bit more integrated and more carefully protected.


Note that one can still save the old $Pre by adding it in front of this code.(one must limit the functionality of old $Pre to an extent that full evaluation of expressions is forbidden)


I think this is probably slower than Kuba's solution in comments, but does



not achieve what you're looking for?

  • $\begingroup$ Oh,we can judge the x<=n in the general case when we debug.such as Table[myEcho[x^2, 3], {x, 10}] just give one result,but it is sure a good think.. $\endgroup$
    – yode
    Mar 23 '17 at 23:20
  • $\begingroup$ This is not what OP wants. n should be the number of times Echo prints, not the upper limit of the number Echo prints. $\endgroup$
    – vapor
    Mar 24 '17 at 6:39
  • $\begingroup$ Ah, sorry, misunderstood what you wanted. How about myEcho[fx_, x_, n_: 5] := If[x <= n, Echo[fx], Identity[fx]], with usage Table[(x^2)~myEcho~x, {x, 10}]? $\endgroup$ Mar 24 '17 at 11:19
  • $\begingroup$ @AnotherShruggingPhysicist What about Table[(x^2)~myEcho~x, {x, 10, 20}]? You cannot assume Table or a iterator like x exists. Even you can, you are also assuming the iterator starting with 1. If you insist on similar approach and remove this x parameter, the best you can achieve is probably the code in the last section of the question. $\endgroup$
    – vapor
    Mar 24 '17 at 14:54

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.