2010-05-10 1 views
5

Я пытаюсь изучить ocaml прямо сейчас и хотел начать с небольшой программы, генерируя все битовые комбинации: ["0", "0", "0"] ["0", " 0" , "1"] [ "0", "1", "0"] ... и так далееOcaml введение

Моя идея заключается в следующем коде:

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

Но я получаю следующая ошибка:

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

Я не понимал, что менять, ты можешь мне помочь?

С наилучшими пожеланиями Philipp

ответ

14

begin foo; bar end выполняет foo и выбрасывает результат в сторону, то он выполняет бар. Поскольку это имеет смысл только в том случае, если foo имеет побочные эффекты и никакого значимого возвращаемого значения ocaml выдаёт предупреждение, если foo имеет возвращаемое значение, отличное от единицы, поскольку все остальное скорее всего будет ошибкой программиста (т.е. программист фактически не намерен результат будет отброшен) - как это имеет место здесь.

В этом случае нет смысла рассчитывать список с «0», а затем выбросить его. Предположительно, вы хотите объединить два списка. Вы можете сделать это с помощью оператора @:

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

Обратите внимание, что я также сделал length = 0 случай возвращения [list] вместо того, чтобы просто list так что результат является списком списков вместо плоского списка.

+0

ааа я вижу, спасибо за объяснение! ты действительно помог мне! –

5

Хотя ответ sepp2k является пятно, я хотел бы добавить следующую альтернативу (который не соответствует подписи вы предложили, но на самом деле делает то, что вы хотите):

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

Первое отличие заключается в том, что вам не нужно передавать пустой список для вызова функции bitsr 2 возвращает [["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]. Во-вторых, он возвращает список упорядоченных двоичных значений. Но что более важно, на мой взгляд, это ближе к духу окамла.

+0

Спасибо за ваш ответ. Мне нравится получать другие идеи! Поскольку я не знаком с Ocaml, это решение более сложно понять. Я дам ему шанс через несколько дней;) –

0

I like to get other ideas!

Так вот ...

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 

Результат:

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

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