2012-09-05 2 views
10

Sono nuovo di OCaml, sto cercando di capire come si suppone di ottenere il valore da un'opzione. Secondo il documento allo http://ocaml-lib.sourceforge.net/doc/Option.html, esiste una funzione get di tipo 'un'opzione ->' a che fa ciò che voglio. ma quando digito:Opzione OCaml get

# let z = Some 3;; 
val z : int option = Some 3 
# get z;; 
Error: Unbound value get 
# Option.get z;; 
Error: Unbound module Option 

Perché non funziona?

+3

Si sta guardando la documentazione di ocaml-lib, una libreria di utilità opzionale per OCaml. Naturalmente non hai bisogno di quella libreria per accedere al valore all'interno di un costruttore 'Some'. –

risposta

14

Il metodo tradizionale per ottenere il valore all'interno di qualsiasi tipo di costruttore in OCaml è l'abbinamento di motivi. L'abbinamento di pattern è la parte di OCaml che può essere più diversa da quella che hai già visto in altri linguaggi, quindi ti consiglio di non scrivere solo programmi nel modo in cui sei abituato (ad esempio aggirare il problema con ocaml-lib) ma provalo e vedi se ti piace.

let contents = 
    match z with 
    Some c -> c;; 

variabile contents è assegnato 3, ma si ottiene un avvertimento:

Attenzione 8: questo pattern-matching non è esaustivo. Ecco un esempio di un valore che non è compensata: Nessuno

Nel caso generale, non si sa che l'espressione si desidera guardare dentro è necessariamente un Some c. Il motivo per cui è stato scelto un tipo di opzione è solitamente che a volte tale valore può essere None. Qui il compilatore ti ricorda che non stai gestendo uno dei possibili casi.

È possibile eseguire la corrispondenza del modello "in profondità" e il compilatore continuerà a verificare se è esaustivo. Considerate questo funzione che prende un (int option) option:

let f x = 
    match x with 
    Some (Some c) -> c 
    | None -> 0 
    ;; 

Qui hai dimenticato il caso Some (None) e il compilatore ti dice così:

Attenzione 8: questo pattern-matching non è esaustivo. Ecco un esempio di un valore che non corrisponde: Nessuno Nessuno

+4

Vale la pena ricordare che il tuo primo esempio è equivalente a 'let Some c = z in c' –

+0

In questa risposta sto usando esclusivamente 'match with' per il pattern matching perché quest'ultimo è l'argomento a portata di mano e non lo penso fa male associarlo a un singolo costrutto in un primo momento. –

+0

Sono d'accordo con te, motivo per cui ho aggiunto questo factoid come commento;) –

9

Il modo normale per farlo è con la corrispondenza del modello.

# let x = Some 4;; 
val x : int option = Some 4 

# match x with 
    | None -> Printf.printf "saw nothing at all\n" 
    | Some v -> Printf.printf "saw %d\n" v;; 
saw 4 
- : unit =() 

È possibile scrivere la propria funzione get (anche se si deve decidere ciò che si vuole fare quando il valore è None).

+0

Questa è una buona risposta.Per espandere questo esempio, facciamo in modo che x tenga una stringa e stampi: https://gist.github.com/shehaaz/7165109 Quindi potenzialmente puoi scrivere una funzione generale che gestisce tutti i tipi. – Shehaaz

4

È necessario ascoltare i consigli sui poster sopra riportati relativi alla sicurezza dei tipi, ma tenere presente che funzioni non sicure come Option.get (che è disponibile nelle batterie btw) sono in genere suffissi con exn. Se sei curioso, allora è possibile implementare Option.get o Option.get_exn:

let get_exn = function 
    | Some x -> x 
    | None -> raise (Invalid_argument "Option.get")