2010-05-10 50 views
5

Tôi đang cố gắng tìm hiểu ocaml ngay bây giờ và muốn bắt đầu bằng một chương trình nhỏ, tạo tất cả các kết hợp bit: ["0", "0", "0"] ["0", " 0" , "1"] [ "0", "1", "0"] ... và vân vânGiới thiệu Ocaml

ý tưởng của tôi là đoạn mã sau:

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

Nhưng tôi nhận được lỗi sau:

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

Tôi không hiểu phải thay đổi gì, bạn có thể giúp tôi không?

Trân trọng Philipp

Trả lời

14

begin foo; bar end thực hiện foo và ném kết quả lập tức, sau đó nó thực hiện thanh. Vì điều này chỉ có ý nghĩa nếu foo có các hiệu ứng phụ và không có giá trị trả về có ý nghĩa, nếu foo có giá trị trả về khác với đơn vị, vì mọi thứ khác có thể là lỗi lập trình (tức là lập trình viên không thực sự có ý định kết quả sẽ bị hủy) - như trường hợp ở đây.

Trong trường hợp này, thực sự không có ý nghĩa gì khi tính danh sách bằng "0" và sau đó vứt nó đi. Có lẽ bạn muốn nối hai danh sách để thay thế. Bạn có thể làm điều này bằng cách sử dụng toán tử @:

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

Lưu ý rằng tôi cũng đã trở lại length = 0 trường hợp [list] thay vì chỉ list nên kết quả là một danh sách liệt kê thay vì một danh sách phẳng.

+0

ahh tôi thấy, cảm ơn bạn đã giải thích! bạn thực sự đã giúp tôi! –

5

Mặc dù câu trả lời sepp2k là tại chỗ trên, tôi muốn thêm các lựa chọn sau (mà không khớp với chữ ký bạn đề xuất, nhưng thực sự làm những gì bạn muốn):

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

Sự khác biệt đầu tiên là bạn không cần phải chuyển danh sách trống để gọi hàm bitsr 2 trả về [["0"; "0"]; ["0"; "1"]; ["1"; "0"]; ["1"; "1"]]. Thứ hai, nó trả về một danh sách các giá trị nhị phân được đặt hàng. Nhưng quan trọng hơn, theo ý kiến ​​của tôi, nó gần gũi hơn với tinh thần của ocaml.

+0

Cảm ơn bạn đã trả lời. Tôi thích nhận các ý tưởng khác! Vì tôi không quen thuộc với Ocaml, giải pháp này là cách phức tạp hơn để hiểu. Tôi sẽ cho nó cơ hội trong một vài ngày;) –

0

I like to get other ideas!

Vì vậy, ở đây nó là ...

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 

Kết quả:

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

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