5
votes

I wish to temporarily rename a built-in symbol and use it with different name while block the main name of this symbol. For example, I wish the following code to print only "2" but not "1" and "3":

Block[{print = Print, Print}, Print[1]; print[2]; Print[3];]

In really the above code prints nothing.

Is it possible to make print working inside such code while completely block symbol Print?

Solutions like

With[{Print = f, print = Print}, Print[1]; print[2]; Print[3];] 

are not suitable since Print is not really blocked inside such code.

The question appeared while thinking on a way to disable tracing of Message internals.

1
Alexey, you do find the difficult questions.Mr.Wizard
And what if you use Hold instead of f? Does that not block Print (but not print) correctly?István Zachar
@István, now it seems clear what you meant. The problem is that With only replaces explicit instances of a symbol, while Block temporarily replaces the symbol for all calls within the Block, even those that are hidden.Mr.Wizard
You are not the only one who would like this functionality. In my fourth post in this thread, groups.google.com/group/comp.soft-sys.math.mathematica/…, I described a hypothetical function Unblock which would do exactly what you want. Ideally, it would work in concert with Block, allowing many levels of nesting of blocking and un-blocking. Unfortunately, AFAIK, there is no built-in Unblock - like function. I'd be happy to learn that I am wrong.Leonid Shifrin

1 Answers

6
votes

This is not very clean, but I believe it is serviceable.

Internal`InheritedBlock[{Print},
  Unprotect[Print];
  Print[x__] := Null /; ! TrueQ[$prn];
  print[x__] := Block[{$prn = True}, Print[x]];
  Print[1]; print[2]; Print[3];
]

If it is not acceptable to have the function replaced with Null in the return, you may need to use something like:

func[x__] := Hold[func[x]] /; ! TrueQ[$prn];

Followed by a ReleaseHold after the Block.

Or:

func[x__] := zz[x] /; ! TrueQ[$prn];

and then follow the Block with: /. zz -> func