8

In two recent questions (1, 2), the previous posters were attempting to control the output order of Plus, which is an Orderless function. Michael Pilat indicated that, internally, Orderless functions Sort their parameters which was causing the difficulty. However, he cautioned against making Plus non-Orderless. The solutions to the two previous questions amount to creating a function that displays like Plus but is not Orderless itself. This is certainly effective, but my question is how can we change the default Sort order?

Community
  • 1
  • 1
rcollyer
  • 10,475
  • 4
  • 48
  • 75
  • 1
    Tricky... The functions `Order`, `OrderedQ`, `Sort` and the attribute `Orderless` all seem to be making separate calls to Mma's *canonical ordering* function. I tried redefining each one of these for the integers and none affected the other. Which is strange considering the documentation says "Ordering[list] gives the positions in list at which each successive element of Sort[list] appears." but changing `Sort` had no effect on `Ordering`. I'm sure if it's possible to change the ordering used by `Orderless` functions. – Simon Nov 06 '10 at 05:30
  • 1
    Also, the `Sort` docs say "Sort[list,p] applies the function p to pairs of elements in list to determine whether they are in order. The default function p is OrderedQ[{#1,#2}]&" but changing `OrderedQ` for the integers has no effect on `Sort`. – Simon Nov 06 '10 at 05:37

1 Answers1

5

I need to do a little more research, but here's two ways; The catch is, you don't actually use the Orderless attribute. Simon should get half-credit for the technique of using pattern-matching with a condition from his answer to question 1 you referenced.

Messing with Order, OrderedQ and Sort won't get you anywhere, because Orderless functions sort with equivalence to those methods, but does not actually sort with them.

The first method, from Simon's answer, is to use a Condition:

In[1]:= ClearAll[f, g]

In[2]:= f[stuff__] /; ! OrderedQ[{stuff}, Greater] := 
           f[Sequence@@Sort[{stuff}, Greater]]

In[3]:= f[1, 2, 3]
Out[3]= f[3, 2, 1]

In[4]:= f[3, 2, 1]
Out[4]= f[3, 2, 1]

That definition of f[stuff__] is evaluated if the order of the arguments is not the order desired, and then transformed into that order.

Another technique is to get a little more low-level and use $Pre or $PreRead:

In[5]:= $Pre = 
 Function[{expr}, 
  expr /. g[stuff__] :> g[Sequence @@ Sort[{stuff}, Greater]]];

In[6]:= g[1, 2, 3]
Out[6]= g[3, 2, 1]

In[7]:= g[3, 2, 1]
Out[7]= g[3, 2, 1]

There are some issues with both of these approaches as they stand, for example, that particular $Pre function doesn't play well with e.g. HoldForm[g[1,2,3]].

So, that's something to play with for now. I hope to update after I do a little more research into this.

Community
  • 1
  • 1
Michael Pilat
  • 6,480
  • 27
  • 30
  • Nice. I never thought of doing the sorting with `$Pre`/`$PreRead`. But as you said, this doesn't solve the original question of changing the sort order for an Orderless function. Note that Orderless is highly optimised and is a heap faster than the Conditional sorting definition used here. – Simon Nov 06 '10 at 07:31
  • Right, but keep in mind that `Orderless` implies that order of the elements doesn't matter, but the fact that you want to sort them in a non-standard way implies that it does, so why use `Orderless`? I think we're left finding the best possible way to transparently sort arguments in an ordered expression. Besides sorting, `Orderless` has other semantic meaning in expressions under various circumstances, like pattern-matching. – Michael Pilat Nov 06 '10 at 07:43
  • your question of why choose `Orderless` when we wish to have a specific sorting order I think misses the point. You are correct in that order is somewhat important, but it is more for aesthetics rather than having any bearing on how Mathematica comprehends the functions themselves. As I understand it, the arguments are sorted to create an `Orderless` system from an ordered one. To me, this implies that any sort order is valid, as long as it is consistent. Since, the choice of sort order is arbitrary by virtue of the function being orderless, why can't we use one that we specify? – rcollyer Nov 08 '10 at 17:31
  • any additional thoughts on this? – rcollyer Dec 08 '10 at 23:12