Quello che stai cercando di fare è chiamato un modello di uguaglianza, e non è fornito da Objective Caml. Obiettivo I modelli di Caml sono statici e puramente strutturali. Ovvero, se un valore corrisponde al modello dipende esclusivamente dalla struttura del valore e in un modo determinato al momento della compilazione. Ad esempio, (_, _)::tail
è un modello che corrisponde a qualsiasi elenco non vuoto la cui testa è una coppia. (identifier, value)::tail
corrisponde esattamente agli stessi valori; l'unica differenza è che quest'ultimo si lega altri due nomi identifier
e value
.
Sebbene alcune lingue abbiano schemi di uguaglianza, ci sono considerazioni pratiche non banali che le rendono problematiche. Quale uguaglianza? uguaglianza fisica (==
in OCaml), l'uguaglianza strutturale (=
in OCaml), o qualche tipo dipendente uguaglianza personalizzato? Inoltre, in Ocaml, esiste una chiara indicazione sintattica di quali nomi sono i raccoglitori e quali nomi fanno riferimento a valori precedentemente associati: qualsiasi identificatore minuscolo in un modello è un raccoglitore. Queste due ragioni spiegano perché Ocaml non ha schemi di uguaglianza. Il modo idiomatico di esprimere un modello di uguaglianza in Ocaml è in una guardia. In questo modo, è immediatamente chiaro che la corrispondenza non è strutturale, che identifier
non è vincolato da questo abbinamento di modelli e che l'uguaglianza è in uso. Per quanto riguarda il brutto, questo è negli occhi di chi guarda - come abituale programmatore Ocaml, trovo brutti i modelli di uguaglianza (per le ragioni sopra).
match bindings with
| (id, value)::tail when id = identifier -> value
| (_, _)::tail -> getValue identifier tail
| [] -> -1
in F #, hai un'altra possibilità: active patterns, che consentono di predefinire le guardie che riguardano un singolo sito in un modello.
Il tuo approccio originale mi ricorda l'unificazione di Prolog, è piuttosto dichiarativo che funzionale. – ron