inert wrapping function

*To*: mathgroup at smc.vnet.net*Subject*: [mg5592] inert wrapping function*From*: "w.meeussen" <w.meeussen at solair4b.eunet.be>*Date*: Fri, 27 Dec 1996 01:59:03 -0500*Sender*: owner-wri-mathgroup at wolfram.com

hi, I need to develop and refine an inert wrapping function. I found to my surprise that it takes quite some thought. With 'inert wrapping function' I mean a label like 'fatty acid', 'fa[]', that behaves like a kind of Type such as 'Integer' or 'Character'. Is there a way to make fa[] Flat, not only over sequences of arguments, but over sums and (scalar) products ? Call it 'LinearlyFlat' or so. The only thing it should do is to automatically Thread over sums or linear combinations of fa[]'s : fa[a fa[A] + b fa[B] + c fa[C] ] should evaluate to a fa[A] + b fa[B] + c fa[C] and, fa[a fa[A] + b fa[ fa[ a fa[A] + b fa[B] + c fa[C] ] ] should evaluate to : a fa[A] + b fa[ a fa[A] + b fa[B] + c fa[C] ] and even further to, finally : a fa[A] + b a fa[A] + b^2 fa[B] + b c fa[C] for clarity, I chose capital lettres for the arguments of the innermost fa[]'s. Those capital arguments should of course never loose their fa[]-wrapper! Something like 'A+B' makes no sense, and neither does fa[a] (since a is just a numeric, not a fatty acid identifier) After some hours of clobbering 'round in the murk, I came up with a temporary cludge : In[224]:= SetAttributes[fa,{Flat,OneIdentity}] In[225]:= fa[id_Plus]:=Thread[Hold[fa][id//Expand],Plus]//ReleaseHold In[226]:= fa[a___ fa[b_]]:=a fa[b] several things make me feel uneasy : fa[id_Plus]:=Thread[fa[id],Plus] doesn't work (infinite recursion ?!), but fa[id_Plus]:=Thread[dummy[id],Plus]/.dummy->fa is ok at first sight. the extra 'Expand' is needed in case a term like .. + p( q fa[] + r fa[] ) appears. I'm not shure if wrapping a 'Hold' around the head 'fa' is orthodox practice to avoid the unexpected infinite recursion in line 225. The trick with the dummy function is not exactly what is needed either, since fa[] is meant to Thread over any number of nested levels of fa[]'s. I have a s t r o n g feeling of re-inventing the wheel here. The nagging feeling persists that, somewhere in 'The Book', all this is already discussed at length. But I can not find it. The use of a function (purely as head) seems to be evident, but to work it out this deep just to make it behave linear feels like Overkill. ------------------------------------------ Please, check any suggestions against the following nasty test that creates a nested list of fa[]'s : All fA, ... fL should end up inside a wrapper fa[], end all a ... l outside of it. a1={fA,fB,fC,fD,fE,fF} a2={a,b,c,d,e,f}; a2=a2/Plus@@a2 b1={fG,fH,fI,fJ,fK,fL} b2={g,h,i,j,k,l}; b2=b2/Plus@@b2 (fb/@a1) . a2 %/.fb[fC]->(fb/@b1) . b2 Nest[#/.fb[fJ]->(fb/@b1) . b2 &,%,3]//fb (* now, replacing fb[] with fa[] should be linear in the fa[]'s : *) Timing[final=%//.fb->fa] (* since it's linear, no big deal to collect the fa[]'s : *) Collect[final,_fa]//Timing Suggestions or pointers to The Book warmely wellcomed. Tanx for reading this far, Dr. Wouter L. J. MEEUSSEN w.meeussen at solair4b.eunet.be