Re: Foo /: Plus[b_Foo] := b
- To: mathgroup at smc.vnet.net
- Subject: [mg114567] Re: Foo /: Plus[b_Foo] := b
- From: Andrzej Kozlowski <akoz at mimuw.edu.pl>
- Date: Wed, 8 Dec 2010 06:40:04 -0500 (EST)
First, there is no bug. Second: this is all due to the Flat and OneIdentity attributes of Plus, or rather the effect these attributes have on pattern matching. You can show this in two ways. One, just remove the OneIdentity attribute of Plus and the behaviour will go away (but of course Plus will no be seriously deranged): ClearAttributes[Plus, OneIdentity] Foo /: Plus[b_Foo] :== b; In[6]:== 1 + Foo[1] Out[6]== Foo(1)+1 Alternatively, define a new function plus with both of these attributes: SetAttributes[plus, {Flat, OneIdentity}] Foo /: plus[b_Foo] :== b; Now plus[1, Foo[1]] produces the same behaviour as you saw with Plus. The best explanation I know appeared a long time ago on this forum and was due to Allan Hayes. It is quite complex and I am not prepared to try to repeat it here. In any case, it should still be possible to find it in the archives. (It may perhaps also appear on other Mathematica related pages with or without attribution to Allan but it certainly was he who succeeded best in decoding this riddle). The behaviour of these attributes is certainly not fully documented and probably will never be. Why? I guess it is because it belongs to the very foundations of the Mathematica language and I think there is nobody today at Wolfram who still thinks about such issues but this is, of course, just a guess. I think Allan's explanation will always remain as close as anyone will ever come to explaining this matter. Andrzej Kozlowski On 7 Dec 2010, at 12:46, kj wrote: > An innocent-looking upvalue for a brand new symbol Foo: > > In[1]:== Foo /: Plus[b_Foo] :== b; > > > Nothing shocking about this rule: it just recapitulates the default > behavior of Plus when given a single argument. And it seems to > work: > > In[2]:== Plus[Foo[1]] > Out[2]== Foo[1] > > > ...but disaster lurks just around the corner: > > In[3]:== 1 + Foo[1] > During evaluation of In[3]:== $IterationLimit::itlim: Iteration limit of 4096 exceeded. >> > Out[3]== Hold[1 + Foo[1]] > > > I was expecting that 1 + Foo[1] would evaluate to itself, not an > infinite loop.... So I examined a trace: > > In[4]:== ToString[ > StringForm["``", > FullForm /@ Take[Quiet[Trace[1 + Foo[1]]], 10] // ColumnForm]] > > Out[4]== "HoldForm[Plus[1, Foo[1]]] > HoldForm[Plus[1, Foo[1]]] > HoldForm[Plus[1, Foo[1]]] > HoldForm[Plus[1, Foo[1]]] > HoldForm[Plus[1, Foo[1]]] > HoldForm[Plus[1, Foo[1]]] > HoldForm[Plus[1, Foo[1]]] > HoldForm[Plus[1, Foo[1]]] > HoldForm[Plus[1, Foo[1]]] > HoldForm[Plus[1, Foo[1]]]" > > > > > Judging from the trace, the evaluator is attempting to evaluate > the same expression over and over. The evaluator is supposed to > stop when it reaches a fixed point, and that looks like a fixed > point if I ever saw one. (In fact, in this case, we started at > the fixed point to begin with!) So either there's a very serious > bug in the evaluator, or the documentation I read on the subject > was wrong about how it's supposed to work. (FWIW, this is Mathematica > 7.) > > > Whatever it is that I'm doing wrong, it seems to me *very fundamental*. > IOW, this does not look to me like some obscure corner case. If > so, I can't understand how I could have missed it in all the reading > I've done about Mathematica over the years. It's occurrences like > this that fuel my *paranoia* about the Mathematica documentation. > > If someone can tell me 1) what I'm doing wrong above, and hopefully > 2) how to fix it, I'd much appreciate it. Also, if you could point > me to where in the documentation I would have learned the answers > to these questions I'd be grateful. > > TIA! > > ~kj > > >