Flat: Problems & Workarounds
- To: mathgroup at smc.vnet.net
- Subject: [mg8418] Flat: Problems & Workarounds
- From: Johan Gunnarsson <johan at isy.liu.se>
- Date: Sat, 30 Aug 1997 00:42:25 -0400
- Organization: Linköping University, Sweden
- Sender: owner-wri-mathgroup at wolfram.com
This is the result from my work trying to construct a associative function. Assume I want a associative function h[] which treats numerical arguments specially. Starting from the template in Roman Maeders "Programming in Mathematica", 3rd ed. I define h[] as In[3]:= SetAttributes[h,{Flat,OneIdentity}] h[x_,y_?NumericQ] := f[y,x] h[x_?NumericQ,y_] := f[x,y] h[x_] := x h[] = 1 Now we try this out by In[8]:= h[2,a,3] Out[8]= f[3,f[2,a]] which is what I want, but if none of the arguments are numeric we get In[9]:= h[a,b] $IterationLimit::"itlim": "Iteration limit of \!\(20\) exceeded." Out[9]= Hold[h[a,b]] This result is reasonable since none of the binary definitions match in this case and we therefore get an infinite loop from the rule h[x_]:=x since the Flat attribute makes h[h[a,b]] equal to h[a,b]. To call this a longstanding bug might be wrong, even though this is certainly a problem. Roman Maeder suggest to move the attribute definition after the rules. The way I understood this was the following In[10]:= ClearAll[h] h[x_,y_?NumericQ] := f[y,x] h[x_?NumericQ,y_] := f[x,y] h[x_] := x h[] = 1 SetAttributes[h,{Flat,OneIdentity}] This gives the following results In[16]:= h[2,a,3] Out[16]= h[2,a,3] Surprisingly enough it seems that by putting the SetAttributes at the end makes the attributes inactive. Is this the correct behavior? The second test shows that the infinite loop is gone. In[17]:= h[a,b] Out[17]= h[a,b] Good! By searching for my workaround, I found the peculiar behavior of Mathematica conditions which I use in the following In[18]:= ClearAll[h] SetAttributes[h,{Flat,OneIdentity}] h[x_,y_?NumericQ] := f[y,x] h[x_?NumericQ,y_] := f[x,y] h[x_] /; Head[Unevaluated[x]]=!=h := x h[] /; True= 1 This gives the following results In[24]:= h[2,a,3] Out[24]= f[3,f[2,a]] In[25]:= h[a,b] Out[25]= h[a,b] which is the behavior I want. The defintion h[] /; True = 1 which seams to be nonsense, prevents the pattern matcher from the infinite loop. Otherwise we would get the tests h[a,b], h[1,a,b], h[1,1,a,b], h[1,1,1,a,b] and so on since h[] is interpreted as the neutral element. Note that the condition must be placed outside the list of arguments. The reason for this is exemplified by the following. In[34]:=SetAttributes[test,{HoldAll}] test[___] := False In[36]:= SetAttributes[g,{Flat,OneIdentity}] g[args__] /; test[args] := foo[args] In[38]:= Trace[g[a,b,c],test[___]] Out[38]= {{test[a,b,c]}} In the case above the condition is outside the arguments and the pattern matcher try once with all the arguments. If we place the condition inside we get In[39]:= ClearAll[g] SetAttributes[g,{Flat,OneIdentity}] g[args__ /; test[args]] := foo[args] In[42]:= Trace[g[a,b,c],test[___]] Out[42]={{test[a,b,c]},{test[a,b]},{test[b,c]},{test[a]},{test[b]},{test[c]}} which shows that all combinations of the arguments are tested. This is not only giving bad performance. It is also a completely different behavior of the pattern matcher. Is this a feature or a bug? Is it documented? Is it possible to make a nice design of an associative function? Sincerely /Johan Gunnarsson -- _____________________________________________________ Johan Gunnarsson | Division of Automatic Control /|\ Dept. of EE, Linkoping University \|/ S-581 83 Linkoping, Sweden /|\ Tel: +46 13 282913 / | \ Fax: +46 13 282622 () | () Email: johan at isy.liu.se WWW: http://control.isy.liu.se/~johan