2010-05-10 23 views
5

estoy tratando de aprender ocaml en este momento y quería comenzar con un pequeño programa, generando todas las combinaciones de bits: ["0", "0", "0"] ["0", " 0" , "1"] [ "0", "1", "0"] ... y así sucesivamenteOcaml introducción

Mi idea es la siguiente código:

let rec bitstr length list = 
    if length = 0 then 
    list 
    else begin 
    bitstr (length-1)("0"::list); 
    bitstr (length-1)("1"::list); 
    end;; 

pero me da la siguiente error:

Warning S: this expression should have type unit. 
val bitstr : int -> string list -> string list = <fun> 
# bitstr 3 [];; 
- : string list = ["1"; "1"; "1"] 

No entendí qué cambiar, ¿me puedes ayudar?

Saludos Philipp

Respuesta

14

begin foo; bar end ejecuta foo y tiros el resultado de distancia, entonces se ejecuta la barra. Dado que esto solo tiene sentido si foo tiene efectos secundarios y no tiene un valor significativo de retorno ocaml emite una advertencia si foo tiene un valor de retorno que no sea la unidad, ya que todo lo demás es un error del programador (es decir, el programador no pretende resultado que debe descartarse), como es el caso aquí.

En este caso, realmente no tiene sentido calcular la lista con "0" y luego tirarla. Presumiblemente, usted quiere concatenar las dos listas en su lugar. Para ello, puede utilizar el operador @:

let rec bitstr length list = 
    if length = 0 then 
    [list] 
    else 
    bitstr (length-1)("0"::list) @ bitstr (length-1)("1"::list);; 

Tenga en cuenta que también hice el length = 0 caso de retorno [list] en lugar de sólo list por lo que el resultado es una lista de listas en lugar de una lista plana.

+0

ahh veo, gracias por la explicación! ¡Realmente me ayudaste! –

5

Aunque la respuesta de sepp2k en el clavo, me gustaría añadir la siguiente alternativa (que no coincide con la firma que usted propuso, pero en realidad hace lo que quiere):

let rec bitstr = function 
    0 -> [[]] 
| n -> let f e = List.map (fun x -> e :: x) and l = bitstr (n-1) in 
     (f "0" l)@(f "1" l);; 

La primera diferencia es que no necesita pasar una lista vacía para llamar a la función bitsr 2 devuelve [["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]. En segundo lugar, devuelve una lista de valores binarios ordenados. Pero más importante aún, en mi opinión, está más cerca del espíritu de ocaml.

+0

Gracias por su respuesta. Me gusta obtener otras ideas! Como no estoy familiarizado con Ocaml, esta solución es mucho más compleja de entender. Le daré una oportunidad en algunos días;) –

0

I like to get other ideas!

Así que aquí está ...

let rec gen_x acc e1 e2 n = match n with 
| 0 -> acc 
| n -> (
    let l = List.map (fun x -> e1 :: x) acc in 
    let r = List.map (fun x -> e2 :: x) acc in 
    gen_x (l @ r) e1 e2 (n - 1) 
);; 

let rec gen_string = gen_x [[]] "0" "1" 
let rec gen_int = gen_x [[]] 0 1 

gen_string 2 
gen_int 2 

Resultado:

[["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]] 

[[0; 0]; [0; 1]; [1; 0]; [1; 1]]