Re: @@@ for Version 3??
- To: mathgroup at smc.vnet.net
- Subject: [mg23123] Re: [mg22967] @@@ for Version 3??
- From: Hartmut Wolf <hwolf at debis.com>
- Date: Wed, 19 Apr 2000 02:30:52 -0400 (EDT)
- Organization: debis Systemhaus
- References: <200004050241.WAA01036@smc.vnet.net> <8ch9iv$95n@smc.vnet.net> <Pine.GSO.4.21.0004061746200.23405-100000@flip.eecs.umich.edu> <200004070654.CAA16541@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
See below for more on @@@ and Version 3: Hartmut Wolf schrieb: > > Daniel Reeves schrieb: > > > > > (If you don't have version 4, then replace @@@ by the alternative > > > input form: > > > > > > In[5]:= Hold[F[x] @@@ k] // InputForm > > > Out[5]//InputForm= > > > Hold[Apply[F[x], k, {1}]] > > > ) > > > > Or you can actually replace the > > @@@ > > with > > @@#&/@ > > > > Ugly, but I do it that way so it's easy to switch over to the ver4 way > > sometime in the near future when I can feel sure that my code won't ever > > need to run on ver3 anymore. > > > > Hallo Daniel, > > nice ideom! Yet you have to be cautious when applying it: > > In[1]:= k = {{a1, b1}, {a2, b2}, {a3, b3}} > > In[2]:= f @@@ k > Out[2]= {f[a1, b1], f[a2, b2], f[a3, b3]} > > In[3]:= g /@ f @@@ k > Out[3]= {g[f[a1, b1]], g[f[a2, b2]], g[f[a3, b3]]} > > In[4]:= f @@#&/@ k > Out[4]= {f[a1, b1], f[a2, b2], f[a3, b3]} > > In[5]:= g /@ f @@#&/@ k > Out[5]= {f[g[a1], g[b1]], f[g[a2], g[b2]], f[g[a3], g[b3]]} > > So @@#&/@ is not a "read macro" to be textually substituted by @@@ when > transiting from version 3 to 4 (or vice versa). Of course the correct > expression for In[5] would be: > > In[6]:= g /@ (f @@ # &) /@ k > Out[6]= {g[f[a1, b1]], g[f[a2, b2]], g[f[a3, b3]]} > > The full form Apply[f, k, {1}] however remains correct in any case for > both versions. > > If you want to have a true syntactical equivalent substition for @@@ you > may have one; define > > In[16]:= aaa = ( Function[{e}, #1 @@ e ] /@ #2 &) > > In[17]:= f ~aaa~ k > Out[17]= {f[a1, b1], f[a2, b2], f[a3, b3]} > > In[18]:= g /@ f ~aaa~ k > Out[18]= {g[f[a1, b1]], g[f[a2, b2]], g[f[a3, b3]]} > Dear Daniel, this was one of my replies I soon felt uncomfortable with after having pressed the send button too early. First of all, I missed to include a neccessary wink ;-) Second, although I raised a problem, this is not the solution, not at all a "true syntactical equivalent". What is still flawed are the associativity rules for @@@, @@, /@. In Version 4 these operators all are of equal precedence and group to the right: With aaa = Apply[#1, #2, {1}] & however ~aaa~ groups to the left, and the precedence is one above @@ and /@, see: In[21]:= g @@@ f @@@ k === g ~aaa~ f ~aaa~ k Out[21]= False In[22]:= g @@@ f @@@ k === g ~aaa~ (f ~aaa~ k) Out[22]= True In[23]:= g @@@ f @@ k === g ~aaa~ f @@ k Out[23]= False In[24]:= g @@@ f @@ k === g ~aaa~ (f @@ k) Out[24]= True In[25]:= g @@@ f /@ k === g ~aaa~ f /@ k Out[25]= False In[26]:= g @@@ f /@ k === g ~aaa~ (f /@ k) Out[26]= True However, when you always explicitly parenthesize your expressions you can safely use your suggested (elegant I think it is) ideom: In[27]:= g @@@ f @@@ k === g ~aaa~ (f @@ # & /@ k) Out[27]= True For some days I pondered the question: can we do better? First of all, I think we cannot define @@@ as new operator in Version 3. The front end scanner will separate this into the two tokens @@ and @ on the fly on sequential input (this is from version 3): f @@ @ g (Only input cell, key [Enter] not pressed yet.) If we activate Show Expression from the Format menu (or press [Ctrl]+[Shift]+[e]) we see (and still nothing evaluated): Cell[BoxData[ RowBox[{"f", " ", "@@", RowBox[{"@", " ", "g"}]}]], "Input"] (You can see from that expression, that no Space was input between the second and third '@'.) An idea would be to use Low-Level Input Rules (as explained in §2.8.17); however we must first find an input string which we can use for reworking the parsed input. After some futile trials I came up with the sequence f @$@ g Cell[BoxData[ RowBox[{"f", " ", "@", RowBox[{"$", "@", " ", "g"}]}]], "Input"] which interpreted in FullForm is of course just f[$[g]] I think, you will never come across the symbol $ to have a value, contrary to 'q' (which else I would have preferred for input ergonomy) << now quit the kernel and restart >> In[1]:= MakeExpression[ RowBox[{f_, "@", RowBox[{"$", "@", g_}]}], StandardForm] := MakeExpression[RowBox[{"mapply", "[", f, ",", g, "]"}], StandardForm] We try it: In[2]:= k = {{a1, b1}, {a2, b2}, {a3, b3}} In[3]:= f @$@ k Out[3]= mapply[f, {{a1, b1}, {a2, b2}, {a3, b3}}] In[4]:= g @$@ f @$@ k Out[4]= mapply[g, mapply[f, {{a1, b1}, {a2, b2}, {a3, b3}}]] So all what we have to do is define mapply: In[5]:= mapply[f_, g_] := Apply[f, g, {1}] In[6]:= f @$@ k Out[6]= {f[a1, b1], f[a2, b2], f[a3, b3]} So it works! Grouping turned out to be right (automatically, as a consequence of the grouping of @). Now how to get the right precedence with @@ and /@ ? Again we locally manipulate the parse tree: In[8]:= MakeExpression[RowBox[{ RowBox[{f_, "@", RowBox[{"$", "@", g_}]}], "@@", h_}], StandardForm] := MakeExpression[RowBox[{"mapply", "[", RowBox[{f, ",", RowBox[{g, "@@", h}]}], "]"}], StandardForm] In[9]:= MakeExpression[RowBox[{ RowBox[{f_, "@", RowBox[{"$", "@", g_}]}], "/@", h_}], StandardForm] := MakeExpression[RowBox[{"mapply", "[", RowBox[{f, ",", RowBox[{g, "/@", h}]}], "]"}], StandardForm] With that things seem to work: In[10]:= g @@@ f @@@ k === g @$@ f @$@ k Out[10]= True In[11]:= g @@@ f @@ k === g @$@ f @@ k Out[11]= True In[12]:= g @@@ f /@ k === g @$@ f /@ k Out[12]= True Of course also In[13]:= g /@ f @$@ k Out[13]= {g[f[a1, b1]], g[f[a2, b2]], g[f[a3, b3]]} In[14]:= g @@ f @$@ k Out[14]= g[f[a1, b1], f[a2, b2], f[a3, b3]] I tried more cases, they all worked. I would be interested if someone finds a hole in it! Kind regards, Hartmut
- References:
- best solution?
- From: "Peter Weijnitz" <peter.weijnitz@perimed.se>
- Re: best solution?
- From: Hartmut Wolf <hwolf@debis.com>
- best solution?