2010-05-10 15 views
5

Staram się teraz nauczyć ocaml i chciałbym zacząć od małego programu, generując wszystkie kombinacje bitów: ["0", "0", "0"] ["0", " 0" , "1"] [ "0", "1", "0"] ... i tak dalejWprowadzenie do Ocaml

Mój pomysł jest następujący kod:

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

ale pojawia się następujący błąd:

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

Nie rozumiem, co zmienić, czy możesz mi pomóc?

poważaniem Philipp

Odpowiedz

14

begin foo; bar end wykonuje foo i wyrzuca wynik z dala, to wykonuje poprzeczkę. Ponieważ ma to sens tylko wtedy, gdy foo ma efekty uboczne i nie ma znaczącej wartości zwrotnej, ocaml wysyła ostrzeżenie, jeśli foo ma wartość zwracaną inną niż jednostka, ponieważ wszystko inne może być błędem programisty (tj. Programista faktycznie nie planuje wynik do odrzucenia) - tak jak ma to miejsce w tym przypadku.

W tym przypadku nie ma sensu obliczanie listy za pomocą "0", a następnie odrzucanie jej. Prawdopodobnie zamiast tego chcesz połączyć dwie listy. Można to zrobić za pomocą operatora @:

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

Zauważ, że zrobiłem również length = 0 przypadku zwrotu [list] zamiast tylko list więc wynik jest lista list zamiast płaskiej listy.

+0

ahh widzę, dziękuję za wyjaśnienie! naprawdę mi pomogłeś! –

5

Chociaż odpowiedź sepp2k jest na miejscu, chciałbym dodać następującą alternatywę (co nie pasuje do podpisu Ci zaproponowane, ale faktycznie robi to, co chcesz):

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);; 

Pierwszą różnicą jest to, że nie trzeba przekazywać pustej listy, aby wywołać funkcję bitsr 2 zwraca [["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]. Po drugie, zwraca listę uporządkowanych wartości binarnych. Ale co ważniejsze, moim zdaniem jest bliższy duchowi ocaml.

+0

Dziękuję za odpowiedź. Lubię zdobywać inne pomysły! Ponieważ nie jestem zaznajomiony z Ocaml, to rozwiązanie jest o wiele bardziej skomplikowane do zrozumienia. Dam mu szansę za kilka dni;) –

0

I like to get other ideas!

Więc tutaj jest ...

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 

Wynik:

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

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