2016-12-14 7 views
5

docs for the Pervasives.compare function Der Zustand, dassKann man etwas anderes als -1, 0 und 1 vergleichen?

compare x y kehrt 0 wenn x zu y gleich ist, wenn eine negative ganze Zahl kleiner als xy, und eine positive ganze Zahl, wenn x größer als y.

Dies legt nahe, es jede negative oder positive ganze Zahl zurückkehren kann, nicht nur -1 oder 1, Größer oder weniger Heit darzustellen. Aber passiert tatsächlich?

Dies würde das Schreiben von Code wie

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) 

viel schwieriger machen (when verwenden, wahrscheinlich?).

Ich bin besonders interessiert an String.compare. Sehen Sie sich its implementation an, es wird nur an Pervasives.compare weitergeleitet, was wiederum nativ mit external implementiert wird. Keine Ahnung was es macht.

+1

Ich habe gerade angefangen OCaml zu lernen. Es ist wirklich cool zu sehen, dass du auf diesem Tag postest^_^ – naomik

Antwort

3

Ich frage mich, warum man den Wrapper @kne nicht direkt vorschlagen sollte. Ihr Code würde werden:

Das spart den Funktionsaufruf und ist nicht wesentlich länger als die -1/0/1-Ansatz. Abgesehen davon wird der Vergleich häufig durch den Benutzer bereitgestellt (siehe z. B. Set.OrderedType), wo die Beschränkung trotzdem verletzt werden kann.

+0

Ja, das wäre meine Lösung der Wahl, aber ich fragte mich, ob das idiomatisch ist? Wird dieses Konstrukt in Enterprise-Ocaml-Projekten verwendet? – Bergi

+0

Ich programmiere nicht Enterprise-Level-OCAML, aber Mustererkennung über wann ist ziemlich häufig. –

3

Kommt das tatsächlich vor?

No.

Pervasives.compare nativ external Verwendung umgesetzt.

Ich denke, dies zu compare.c bezieht, die die string case mit nicht implementiert

#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; 

So scheint es, dies in der Tat eine beliebige ganze Zahl ist für Strings wie compare "a" "abc" (-2) zurückkehren konnte.

Aber wenn wir in Ocaml versuchen, geschieht dies nicht und gibt einfach -1 zurück. Warum nicht?
Da die real compare function, die Ocaml Code ausgesetzt ist, hat die Ergebnisse zu normalisieren:

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); 
} 

es kann also in der Tat keine int andere Rückkehr als diese drei.

6

Eine Antwort von Ihnen selbst zeigt, dass keine anderen Werte in der aktuellen Implementierung zurückgegeben werden können. Ich wäre jedoch sehr vorsichtig, mich darauf zu verlassen. Solange compare nicht als dreiwertig dokumentiert ist, können zukünftige Versionen von OCaml dieses Verhalten ändern.

[EDIT, um einen Kommentar zu beantworten] Um zu vermeiden, plump Fallunterscheidungen (wie in Ihrer ursprünglichen Frage angedeutet), Sie compare in eine Funktion wickeln können, die gibt einen Drei-Werte geben wie so:

type comparison = Less | Equal | More 

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

Ja, dem stimme ich vollkommen zu. Wie also würde ein idiomatischer Drei-Wege-Vergleich in Ocaml aussehen? – Bergi

+0

Warum gibt es in der Standardbibliothek keinen solchen Vergleichstyp? – Bergi