(The below was prompted by a real world use case, in which I had to determine the minimum required encoding scheme (labeled by atoms) for a binary, by traversing it and looking at the individual bytes. For the sake of discussion, I have abstracted and abbreviated the problem, in hope to make it simpler for everyone to follow.)
Say you have a limited set of known distinct terms, for example one
, two
and three
.
In implicit Erlang term order, which in this case coincides with alphabetic ordering, their order is one < three < two
. Their semantic ordering (unknown to Erlang of course, but known to you), however, is one < two < three
.
Implementing functions for determining the min/max of two values for this semantic ordering is very verbose, the best I could come up with at first was something like this for max
…
max2(three, _) -> three;
max2(_, three) -> three;
max2(two, _) -> two;
max2(_, two) -> two;
max2(one, _) -> one;
max2(_, one) -> one.
… and likewise for min
, just with the clauses reversed.
Devising a function that could be used in sorting is similar to the above, just with true
s and false
s as return values in the proper places.
Not exactly hard, but really tedious. There are 3 terms in this example, what if you have 100? And the function is specific to this very set, what if you have more different ones?
Is there a better, more general way to do this? The best I could come up with is this:
which([T1|_], T1, _T2) -> T1;
which([T2|_], _T1, T2) -> T2;
which([_|Rest], T1, T2) -> which(Rest, T1, T2).
which
takes the terms of the set ordered according to the semantic rules as first argument, and the two terms to compare as second and third. It returns the term which appears first in the order list.
min
can be realized by giving the order in ascending order, max
by giving it in descending order.
A generalized sort function for explicit orders could be something like this:
sort(Order, List) ->
lists:sort(
fun (T1, T2) -> which(Order, T1, T2)=:=T1 end,
List).
So far, this is my best shot. Are there other, better known ways or ideas to achieve this?