2012-09-05 9 views
10

Soy nuevo en OCaml, estoy tratando de entender cómo se supone que debe obtener el valor de una opción 'a'. De acuerdo con el documento en http://ocaml-lib.sourceforge.net/doc/Option.html, hay una función get de tipo 'a option ->' a que hace lo que quiero. pero cuando escribo:Opción OCaml obtener

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

Why isnt this working?

+3

Está buscando en la documentación de ocaml-lib, una biblioteca de utilidad opcional para OCaml. Por supuesto, no necesita esa biblioteca para acceder al valor dentro de un constructor 'Some'. –

Respuesta

14

La forma tradicional de obtener el valor dentro de cualquier tipo de constructor en OCaml es con la coincidencia de patrones. La coincidencia de patrones es la parte de OCaml que puede ser más diferente de lo que ya has visto en otros idiomas, por lo que te recomendaría que no solo escribas programas de la forma en que estás acostumbrado (por ejemplo eludir el problema con ocaml-lib) pero en su lugar pruébalo y mira si te gusta.

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

variable contents se asigna 3, pero se obtiene una advertencia:

Advertencia 8: este patrón de coincidencia no es exhaustiva. Este es un ejemplo de un valor que no es igualada: Ninguno

En el caso general, no se sabe que la expresión que desea buscar en el interior es necesariamente una Some c. La razón por la que se eligió un tipo de opción es que a veces ese valor puede ser None. Aquí el compilador te recuerda que no estás manejando uno de los posibles casos.

Puede hacer coincidir patrones "en profundidad" y el compilador aún comprobará la exhaustividad. Considere esta función que toma un (int option) option:

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

Aquí se le olvidó el caso Some (None) y el compilador se lo indique:

Advertencia 8: este patrón de coincidencia no es exhaustiva. Aquí hay un ejemplo de un valor que no se corresponde: Algunos Ninguno

+4

Vale la pena mencionar que su primer ejemplo es equivalente a 'let Some c = z in c' –

+0

En esta respuesta estoy usando exclusivamente 'match with' para la coincidencia de patrones porque este último es el tema que nos ocupa y no lo creo duele asociarlo a una sola construcción al principio. –

+0

Estoy de acuerdo con usted, razón por la cual agregué este factoid como un comentario;) –

9

La forma habitual de hacerlo es con la coincidencia de patrones.

# 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 =() 

Usted puede escribir su propia función get (aunque usted tiene que decidir lo que quiere hacer cuando el valor es None).

+0

Esa es una buena respuesta.Para expandir ese ejemplo, hagamos que x sostenga una cadena e imprima eso: https://gist.github.com/shehaaz/7165109 Así que potencialmente puede escribir una función general que maneje todos los tipos. – Shehaaz

4

Debe escuchar los consejos anteriores sobre el tipo de seguridad, pero también tenga en cuenta que las funciones inseguras como Option.get (que está disponible en baterías por cierto) suelen tener el sufijo de exn. Si tiene curiosidad, así es como Option.get u Option.get_exn podrían implementarse:

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