What is the canonical way to write a compare: t -> t -> int function that takes a number of components of t into account? Here is an example but I’m not sure about the most natural way to implement it:
type t =
{ a: string
; b: int
; c: float
}
let ts =
[ {a="a1"; b=2; c=1.0}
; {a="a2"; b=3; c=0.0}
]
(** sort by c, b, a *)
let cmp t1 t2 =
let x = compare t1.c t2.c in
if x <> 0 then x else
let x = compare t1.b t2.b in
if x <> 0 then x else
compare t1.a t2.a
I realise that the indentation is not correct - I wanted to emphasise that components are compared in a linear order with most significant components first.
#require "ppx_deriving.ord";;
type t =
{ a: string
; b: int
; c: float
}
[@@deriving ord]
That will generate you a suitable compare function automatically.
If you want to write it manually, I suggest writing the function as let compare {a; b; c} other = .... That way, the compiler will warn you if new fields get added later.
The reason not to rely on the generic compare is that I would want to ignore some fields or give some precedence over others. Is this supported by the PPX?
@anon72795300 There is no magic at all. What happens is that past the first comparison, you provide triplets of a compare function and two values to be compared, and the triplet is evaluated (meaning the compare function is actually called on the arguments), if and only if the previous comparison returned 0. You can see the code at : https://github.com/c-cube/ocaml-containers/blob/master/src/core/CCOrd.ml#L42
I think the indentation is fine, and this is exactly how I would write it myself (apart from variable names).
It may look strange to someone used to the C-style languages, but note how a C programmer might use a sequence of if (...) return ... in a similar fashion. In pure functional, code return is not a good option as it would count as an effect, at least if you think of it as a continuation rather than syntactic trick. Nevertheless, this eliminate-case-and-proceed style fits very nicely into the OCaml syntax as the an if-then-else is grammatically similar to a let ... in line or a monadic ... >>= fun ... -> line.