docs for the Pervasives.compare
function状态
如果compare x y
等于0
,
x
会返回y
,如果x
小于y
,则返回负整数如果x
大于y
,则为整数。
这表明它可以返回任何负整数或正整数,而不仅仅是-1
或1
来表示更大或更小。但是,确实会发生这种情况?
这样可以编写像
这样的代码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
本机实现的。不知道它做了什么。
答案 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),其中可能违反约束。