可以比较返回除-1,0和1以外的任何内容吗?

时间:2016-12-14 08:07:36

标签: compare comparison ocaml

docs for the Pervasives.compare function状态

  如果compare x y等于0

x会返回y,如果x小于y,则返回负整数如果x大于y,则为整数。

这表明它可以返回任何负整数或正整数,而不仅仅是-11来表示更大或更小。但是,确实会发生这种情况

这样可以编写像

这样的代码
match String.compare key new_key with
  | 1  -> Node (left,                insert new_key right, key)
  | -1 -> Node (insert new_key left, right,                key)
  | _  -> Node (left,                right,                key)

更难(使用when,可能?)。

我对String.compare特别感兴趣。看看its implementation,它只是转发到Pervasives.compare,而Message.get_payload又是使用external本机实现的。不知道它做了什么。

3 个答案:

答案 0 :(得分:6)

您自己的答案表明,在当前的实施中,不能返回任何其他值。不过,我会非常小心地依靠它。只要compare未被记录为三值,OCaml的未来版本可能会改变这种行为。

[编辑,回答评论]为了避免笨拙的案例区别(如原始问题中暗示的那样),您可以将compare包装成一个返回三值类型的函数,如下所示:

type comparison = Less | Equal | More

let my_compare a b = match compare a b with
| 0 -> Equal
| c when c>0 -> More
| _ -> Less

答案 1 :(得分:3)

  

这实际发生了吗?

没有

  

Pervasives.compare是使用external原生实现的。

我认为这是指compare.c,它使用

实现string case
#define LESS -1
#define EQUAL 0
#define GREATER 1

mlsize_t len1 = caml_string_length(v1);
mlsize_t len2 = caml_string_length(v2);
int res = memcmp(String_val(v1), String_val(v2), len1 <= len2 ? len1 : len2);
if (res < 0) return LESS;
if (res > 0) return GREATER;
if (len1 != len2) return len1 - len2;

所以看起来这确实可以为compare "a" "abc"-2)这样的字符串返回一个任意整数。

但是如果我们尝试使用Ocaml,这不会发生,只会返回-1。为什么不呢? 因为暴露给Ocaml代码的real compare function会对结果进行规范化:

CAMLprim value caml_compare(value v1, value v2)
{
  intnat res = compare_val(v1, v2, 1);
  if (res < 0)
    return Val_int(LESS);
  else if (res > 0)
    return Val_int(GREATER);
  else
    return Val_int(EQUAL);
}

所以除了那三个之外,它确实无法返回任何int

答案 2 :(得分:3)

我想知道为什么不应该直接使用包装器@kne。您的代码将成为:

match String.compare key new_key with
  | 0             -> Node (left, right, key)
  | x when x > 0  -> Node (left, insert new_key right, key)
  | _ (* x < 0*)  -> Node (insert new_key left, right, key)

保存函数调用并且不会明显长于-1 / 0/1方法。除此之外,比较通常由用户提供(参见例如Set.OrderedType),其中可能违反约束。