Pattern overriding

This is a place to write thoughts about pattern overriding.

the main idea we had is to keep the rules in a list and when a new rule comes in to check the list from top to bottom and place the new rule directly before the first pattern that is "more specific" than it.

Th problem that we are adressing is the following: consider the patterns

1. f[_]         3. f[_Integer] 2. f[_?Prime]   4. f[_Integer?Prime]

if you have all these rules in your system, there are two logical orders:

4 3 2 1 and 4 2 3 1

The reason is that since 1 is the least specific, if it is before any of the other rules, they will never be seen.

Definition: A pattern Y is "less specific" than pattern X if every match of X also matches Y. Notation: If a pattern Y is less specific than pattern X we will write Y>=X (note the convention, Y matches MORE, hence is bigger...) If two patterns are incomparable (neither is more specific that the other) we write X >< Y           If X<=Y and Y<=X we can write X==Y. "lemma": The relation above is transitive: If X<=Y and Y<=Z then X<=Z.

Similarly, if 4 is not first, it will be "hidden" by whatever is before it. This explains (kindof) why you must always place a pattern before the first pattern that is less specific than it. The relative order between 3 and 4 will have to be determined by the order in which they were put into the system: the one that is put in first, is higher.

The definition of "more specific" is at the moment very theoretical. We are not sure how to determine, for any two patterns X and Y which is more specific. We do have some examples:

__>=_ ___>=__ a<=_ a><_ f[x_,y_]==f[y_,x_]

an intersting point is that the relations above are for the whole patterns. We haven't really come up with a good way of using specificity of subpatterns to determine the pattern of the whole: f[x_,g[x_,y_]] >< f[x_,g[y_,x_]]

Even though the head is the same and the leaves are EACH comparable, the overall effect of the NAMES of the Blanks messes everything up.

A possible solution to this is to rename the Blanks in a smart way. Examples where this is easy:

f[_]==f[x_]

if we noticed that x_ on the right is only used once, and dropped the name, it would be easy.

A little more subtle:

f[x_,_,x_,y_]==f[y_,_,y_,z_]

here we can rename the named blanks according to the the first place where they show up. There are many ways to do this but here's a simple way:

f[x$1_,_,x$1_,x$4_]

This indicates that the first Blank first appeared as the first argument of f and the second as the fourth.

Not clear what to do with

f[x_,y_] <= f[x__]

This renaming scheme isn't that great either. For example, how do you rename these:

f[x_][x_,y_]                  x->x$1, y->x$$2 f[x_,y_][x_,y_,g[y_],z_,z_]   x->x$1, y->x$2, z->x$$4 f[y_,y_]>=f[x_,g[x_]]         LHS: y->x$1, RHS: x->x$1 f[y_,g[x_]>=f[x_,g[x_]]       LHS: y->x$1, x->x$1$1, RHS: x->x$1