2016-01-22 10 views
6

Sono nuovo di OCaml e sto leggendo il libro Real World OCaml (RWO). La corrispondenza del modello è descritta nel capitolo 3 e sembra debole rispetto alla corrispondenza del modello di Erlang (o Prolog).Perché la corrispondenza di OCaml è più debole di quella di Erlang?

Le mie domande sono:

  1. perché è modello di OCaml la corrispondenza più debole?
  2. ci sono dei vantaggi nello stile di corrispondenza dei pattern di OCaml?

Un esempio concreto:

la seguente funzione (. Tratto da RWO p 63) destutters un elenco

let rec destutter list = 
    match list with 
    | [] -> [] 
    | [hd] -> [hd] 
    | hd :: hd' :: tl -> 
     if hd = hd' then ds1 (hd' :: tl) 
     else hd :: ds1 (hd' :: tl) 
    ;; 

# destutter [1;2;3;3;4;5;5;6];; 
- : int list = [1; 2; 3; 4; 5; 6] 

In Erlang sarebbe possibile (e ritengo preferito) da usare modello corrispondenti al posto del condizionale:

destutter([])  -> []; 
destutter([X])  -> [X]; 
destutter([H,H|T]) -> destutter([H|T]); 
destutter([H|T]) -> [H | destutter(T)]. 

Cercando questo genere di cose in OCaml ...

012.
let rec destutter list = 
    match list with 
    | [] -> [] 
    | [hd] -> [hd] 
    | hd :: hd :: tl -> destutter tl (* error *) 
    | hd :: tl -> hd :: destutter tl 
    ;; 

... genera un errore sulla linea segnata:

Error: Variable hd is bound several times in this matching 

Quindi, Erlang pattern matching/stile Prolog non funziona in OCaml. Perché? Quali sono i vantaggi dell'approccio OCaml?

Con Grazie e auguri

Ivan

+0

Domanda molto interessante, ho sicuramente bisogno di saperne di più su Erlang! –

risposta

5

Il modello di Erlang è più potente perché può abbinare contro qualcosa determinato in fase di esecuzione. I pattern OCaml corrispondono a cose risolte in fase di compilazione. Ne consegue che i pattern OCaml possono probabilmente essere fatti andare più velocemente. Trovo anche più semplice ragionare su modelli in stile OCaml.

+1

Grazie per la tua risposta! Tre ottime risposte e molto difficile decidere quale accettare. - Trovi motivi di stile OCAMl più facili da ragionare perché hai più familiarità con OCaml che con Erlang? Come posso crescere ad amare OCaml PMs, proveniente da Erlang? –

4

I modelli in OCaml sono compilati in un codice molto efficiente con un sacco di sophisticated optimizations. Bjarne Stroustrup anche bragged che sono riusciti a scrivere qualcosa di paragonabile in alcuni casi in C++. Ma in generale il match pattern OCaml è molto più veloce. E 'affascinante guardare l'output del gruppo. E forse Erlang offre più flessibilità, ma è previsto da un linguaggio dinamico. Altrimenti perché usarli del tutto.

C'è anche un altro problema. I modelli sono abbinati strutturalmente. Se vuoi abbinare lo [H,H|T] stai effettivamente invocando il confronto dei primi due elementi. Nella maggior parte dei casi, la funzione di confronto dovrebbe essere fornita da un utente e non è nota in anticipo.

+0

Grazie per la tua risposta! Tre ottime risposte e molto difficile decidere quale accettare. –

+0

L'articolo sull'ottimizzazione della corrispondenza dei modelli è affascinante, grazie per aver scritto questa risposta! –

8

In primo luogo, si può sempre cogliere l'uguaglianza tra le variabili del modello tramite una clausola when in OCaml, ad es .:

let rec destutter = function 
    | []    -> [] 
    | [hd]   -> [hd] 
    | hd :: hd' :: tl 
     when hd = hd' -> destutter (hd :: tl) 
    | hd :: hd' :: tl -> hd :: destutter (hd' :: tl) 

C'è un trade-off qui. Mentre Erlang è più espressivo, la corrispondenza di pattern OCaml è più semplice (il che significa una definizione di linguaggio più semplice, un compilatore, ecc.), E puoi ancora fare ciò che ti serve (a costo di scrivere più codice).

Si noti che mentre è possibile riscrivere un motivo non lineare come un modello lineare con una clausola when, non si tratta del problema principale.Più criticamente, la corrispondenza dei modelli deve quindi avere una nozione di uguaglianza per i tipi arbitrari per supportare schemi non lineari. Questo non è un problema in Erlang, ma OCaml non solo ha già = rispetto a == built-in (uguaglianza strutturale vs. identità), ma per ogni tipo specificato, potrebbe non essere il tipo di uguaglianza di cui hai bisogno (pensa a stringhe e caso -sensibilità, per esempio). Quindi, di conseguenza, la verifica dell'esaustività o della sovrapposizione diventa non banale. Alla fine, è discutibile se valga la pena di fornire un caso speciale per un tipo specifico di uguaglianza, dato quante relazioni utili tra le parti di un modello possono esserci. (Prendo atto che le lingue non rigide hanno problemi aggiuntivi.)

Per inciso, la corrispondenza del modello di Prolog è unificata e strettamente più potente di Erlang o OCaml (ma anche più difficile da implementare).

+1

Grazie per la tua risposta! Tre ottime risposte e molto difficile decidere quale accettare. - quando le clausole sono disponibili anche in Erlang (chiamate guardie). Un esempio simile al tuo arriva poco dopo nel libro RWO, ma mi mancheranno i PM in stile Erlang :( –

Problemi correlati