4

I am trying to figure out the logic of Message behavior.

Consider evaluation of the following:

On[]
Sin[1,1]

After evaluating the above you will get about 830 (!) Messages (in Mathematica 7).

All these Messages have arisen during producing the one:

Sin::argx: Sin called with 2 arguments; 1 argument is expected. >>

(this is one but last Message).

The last Message

Message::trace: Message[Sin::argx,Sin,2] --> Null. >>

corresponds to finishing of the work of internal Mathematica's Message function. Most of the other Messages go from evaluation of $NewMessage and $MessagePrePrint.

My questions are:

1) Why there are no infinite loop of Message generation? If calling Message[Sin::argx,Sin,2] produces more than 830 other Messages why each of them does not produce similar number of Messages? How such behavior can be simulated (by writing an analog of Message)?

2) Is it possible to force Message do not produce any additional Messages when it is called in the tracing mode (I mean the mode after evaluating On[])?

Alexey Popkov
  • 9,355
  • 4
  • 42
  • 93

2 Answers2

0

I am not understanding why it is necessary to turn on all the messages with On. Can you not only activate the subset you need. The reference page of On in "More Information" section lists various categories which you might find useful. In case you choose to proceed as stated, you can suppress trace messages by explicitly turning them off right after On[]:

On[]; Off[General::trace];
Sin[1, 1]

This outputs only two messages. Hence 830 of the messages you see are ::trace messages and originate from execution of some top-level code which is not necessarily message related, might be typesetting...

Sasha
  • 5,935
  • 1
  • 25
  • 33
  • 1
    I have investigated this case with some care and the results are explained in my question. All these ::trace `Messages` are generated during evaluation of `Message[Sin::argx,Sin,2]`. At the end there are some calls to `MakeBoxes` but again it is before the last message `Message::trace: Message[Sin::argx,Sin,2] --> Null. >> `. What you suggest is just to turn off tracing at all. I need to turn off only tracing of `Message` internals and/or understand why there is no infinite loop. – Alexey Popkov Apr 25 '11 at 02:46
  • On the reasons of the question consider for example `On[Block];Sin[1, 1]`. If some `Message` is generated inside of a complicated program and I am trying to trace evaluation of some `Symbol` I can get garbage messages from inside `Message` evaluation. I just need to switch off tracing of `Message` internals, not the surrounding code. – Alexey Popkov Apr 25 '11 at 03:21
  • @Alexey I do not think what you ask for is possible, since tracing does not differentiate whether the symbol was used by an internal program or not. I just noticed that running `On[Block];Sin[1, 1]` second time those unwanted messages disappear, and it might help. – Sasha Apr 25 '11 at 13:46
  • In really I have already written my own `Message` implementation that works in the way I am asking for. I just still looking for a way to achieve this with built-in function. And I am really interested to understand why the built-in function does not produce infinite loop. – Alexey Popkov Apr 25 '11 at 14:05
0

It seems that I have found one way to achieve with built-in function Message what I want:

Unprotect[Message];
Message[_, HoldForm[Block[List[$MyMagicalTag$, ___], _]], _] := Null;
Message[args___] /; 
   Block[{$MyMagicalTag$, Message}, Not@TrueQ[inMsg]] := 
  Block[{$MyMagicalTag$, inMsg = True, lastargs = HoldComplete[args]},
    Message[args]];
Message[args___] /; 
   Block[{$MyMagicalTag$, 
     Message}, (inMsg && (HoldComplete[args] =!= lastargs))] := Null;
Protect[Message];

Now things work as expected:

In[6]:= On[]
In[7]:= Sin[1,1]//AbsoluteTiming
During evaluation of In[7]:= Message::trace: Message[Sin::argx,Sin,2] --> Block[{$MyMagicalTag$,inMsg=True,lastargs=HoldComplete[Sin::argx,Sin,2]},Message[Sin::argx,Sin,2]]. >>
During evaluation of In[7]:= Sin::argx: Sin called with 2 arguments; 1 argument is expected. >>
During evaluation of In[7]:= AbsoluteTiming::trace: AbsoluteTiming[Sin[1,1]] --> {0.1502160,Sin[1,1]}. >>
Out[7]= {0.1502160,Sin[1,1]}

The only problem with the above is that CPU load is still high as you can see from the timings.

Other tested cases also work correctly:

In[8]:= 1+1//AbsoluteTiming
During evaluation of In[8]:= Plus::trace: 1+1 --> 2. >>
During evaluation of In[8]:= AbsoluteTiming::trace: AbsoluteTiming[1+1] --> {0.0400576,2}. >>
Out[8]= {0.0400576,2}

Thanks to Mr.Wizard for his help.

Community
  • 1
  • 1
Alexey Popkov
  • 9,355
  • 4
  • 42
  • 93