2010-05-10 26 views
5

ich versuche jetzt okaml zu lernen und wollte mit einem kleinen programm beginnen, das alle bit-kombinationen erzeugt: ["0", "0", "0"] ["0", " 0" , "1"] [ "0", "1", "0"] ... und so weiterOcaml einführung

Meine Idee ist, der folgende Code:

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

aber ich habe die folgender Fehler:

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

Ich habe nicht verstanden, was ich ändern soll. Kannst du mir helfen?

Mit freundlichen Grüßen Philipp

Antwort

14

begin foo; bar end führt foo und wirft das Ergebnis entfernt, dann führt sie bar. Da dies nur Sinn macht, wenn foo Nebeneffekte und keinen sinnvollen Rückgabewert hat ocaml gibt eine Warnung aus, wenn foo einen anderen Rückgabewert als unit hat, da alles andere wahrscheinlich ein Programmierfehler ist (dh der Programmierer beabsichtigt eigentlich nicht für den Ergebnis zu verworfen werden) - wie es hier der Fall ist.

In diesem Fall macht es wirklich keinen Sinn, die Liste mit "0" zu berechnen und dann wegzuwerfen. Vermutlich möchten Sie stattdessen die beiden Listen verketten. Sie können dies den @ Operator tun:

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

Bitte beachte, dass ich auch die length = 0 Fall Rückkehr [list] statt nur gemacht list so das Ergebnis ist eine Liste von Listen statt einer einfachen Liste.

+0

ahh ich sehe, danke für die Erklärung! Du hast mir wirklich geholfen! –

5

Obwohl sepp2k Antwort genau das Richtige ist, würde Ich mag die folgende Alternative hinzuzufügen (die nicht die Signatur, die Sie vorgeschlagen, passt aber tatsächlich tut, was Sie wollen):

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

Der erste Unterschied besteht darin, dass Sie müssen keine leere Liste übergeben, um die Funktion aufzurufen. bitsr 2 gibt [["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]] zurück. Zweitens gibt es eine Liste von geordneten binären Werten zurück. Aber noch wichtiger, meiner Meinung nach liegt es näher am Geist von Ocaml.

+0

Danke für Ihre Antwort. Ich mag es, andere Ideen zu bekommen! Da ich mit Ocaml nicht vertraut bin, ist diese Lösung viel komplexer zu verstehen. Ich werde es in einigen Tagen eine Chance geben;) –

0

I like to get other ideas!

Also hier ist es ...

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 

Ergebnis:

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

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