From: Leonid Shifrin on
Hi Szabolcs & Torsten,

Szabolcs, thanks for this clarification - I should have been more clear.

I believe that what Leonid referred to when he said that it might not
> work if you add pattern based definitions later on was that this
> approach assumed that the "antisymmetry definition" is the very last
> one in the DownValue list.


Yes, that's exactly what I meant. As soon as we attach some condition of
almost any complexity to the rule, it becomes specific (less specific than only
explicit definitions which do not involve patterns at all and are kept internally
in a hash table), even if it's "host" pattern is very general. Therefore, even
patterns that appear less general than the bare "host" pattern, have a pretty
good chance to be interpreted as more general by Mathematica, and therefore
become the last.

Precisely this happens if for example you add the following definition:

In[75]:=G[x_, a] := (x + a)^2;

In[76]:= DownValues[G]

Out[76]= {HoldPattern[G[a, b]] :> f[a, b],
HoldPattern[G[a, c]] :> g[a, c], HoldPattern[G[b, c]] :> h[b, c],
HoldPattern[G[x_, y_]] :> -G[y, x] /;
Hold[G[y, x]] =!= (Hold[G[y, x]] /. Most[DownValues[G]]),
HoldPattern[G[x_, a]] :> (x + a)^2}

In[77]:= G[d, a]

During evaluation of In[77]:= $RecursionLimit::reclim: Recursion depth of
256 exceeded. >>

During evaluation of In[77]:= $RecursionLimit::reclim: Recursion depth of
256 exceeded. >>


The following version will be somewhat more robust:

ClearAll[G];
G[a, b] := f[a, b]
G[a, c] := g[a, c]
G[b, c] := h[b, c]

Module[{this},
G[x_, y_] :=
-G[y, x] /; (this; True) &&
Hold[G[y, x]] =!= (Hold[G[y, x]] /.
DeleteCases[DownValues[G], _?(! FreeQ[#, this] &)])];

But it resorts to DeleteCases and this will result in some performance hit.
This version can take this extra definition added later:

In[86]:= G[x_, a] := (x + a)^2;

In[87]:= G[b, a]

Out[87]= -f[a, b]

In[88]:= G[d, a]

Out[88]= (a + d)^2

In[89]:= G[a, d]

Out[89]= -(a + d)^2



> Mathematica tries to automatically order
> definitions from most specific to most general, but this is not always
> possible. When it can't do this, it just adds rules to the DownValue
> list in the order they were defined. So a general pattern based
> definition *may* displace the antisymmetry rule from the very last
> position, especially if it is added later. Just be careful with the
> order in which definitions are made.
>

Yes, this is exactly the point. (which I think is well -illustrated by the
examples above).

Best,
Leonid