2010-06-15 31 views
7

Tôi đang cố gắng viết một hàm đệ quy đơn giản xem qua danh sách và trả về một cặp nguyên. Đây là dễ dàng để viết trong c/C++/java nhưng tôi mới để OCaml nên bằng cách nào đó khó có thể tìm ra các giải pháp do gõ xung độtcâu hỏi đối sánh mẫu ocaml

nó nên đi như thế ..

let rec test p l = ... ;; 
val separate : (’a -> bool) -> ’a list -> int * int = <fun> 
test (fun x -> x mod 2 = 0) [-3; 5; 2; -6];; 
- : int * int = (2, 2) 

vì vậy vấn đề là cách tôi có thể trả về giá trị đệ quy trên tuple ..

+2

Bạn có thể cung cấp thêm một số chi tiết về chức năng này được cho là sẽ trả về không? Cặp số nguyên thể hiện cái gì? – goggin13

+0

vì vậy nó sẽ trả về một cặp nguyên như (x, y) là tuple trong ocaml mà chỉ có vấn đề mà tôi đã phải đối mặt là tính toán tuple .. do đó, như thế, nếu một phần tử của danh sách là ít thì một số sau đó (x 1, y) khác (x, y + 1) sao cho giá trị trả về sẽ là (x, y) trong đó x là số phần tử lớn hơn một số và y nhỏ hơn – REALFREE

Trả lời

4

Been xa OCaml cho một chút, nhưng tôi nghĩ rằng điều này sẽ làm các trick liên quan đến mô tả REALFREE trong những nhận xét

let rec test l = 
    match l with 
     [] -> (0,0) 
    | x::xs -> 
     if x > 0 then match (test xs) with (x,y) -> (x+1, y) 
     else match (test xs) with (x,y) -> (x, y+1);; 

Bạn có thể sử dụng các báo cáo trận đấu lồng nhau để kéo ra mảnh của tuple để sửa đổi

EDIT: tôi không biết về cú pháp Pascal Cuoq nêu trong bình luận của ông dưới đây, đây là các mã như thế, nó gọn gàng và ngắn hơn một chút:

let rec test l = 
    match l with 
     [] -> (0,0) 
    | x::xs -> 
    if x > 0 then let (x,y) = test xs in (x+1, y) 
    else let (x,y) = test xs in (x, y+1);; 

Nhưng câu trả lời được chấp nhận vẫn tốt hơn nhiều, đặc biệt là với sự đệ quy đuôi;).

+2

và nếu bạn đang viết một 'kết hợp .. với ..' với một mẫu đơn, bạn có thể sử dụng' let' thay thế: 'let x, y = test xs in ...' –

5

Một vấn đề ở đây là bạn đang trả về hai loại khác nhau: một int cho một danh sách trống, hoặc một bộ khác. Nó cần phải là một hoặc khác.

Một vấn đề khác là bạn đang cố gắng thêm 1 đến test, nhưng test là một hàm, không phải là giá trị. Bạn cần phải gọi thử nghiệm trên một cái gì đó khác cho nó để trả về một giá trị, nhưng thậm chí sau đó nó là nghĩa vụ phải trả lại một tuple, mà bạn không thể thêm vào một số nguyên.

Tôi không thể biết bạn muốn mã làm gì, nhưng nếu bạn cập nhật câu hỏi của mình với thông tin đó, tôi có thể trợ giúp thêm.

Một đoán rằng tôi đã là bạn muốn đếm số dương trong danh sách, trong trường hợp này bạn có thể viết nó như thế này:

let rec test l = 
    match l with [] -> 0 
    | x::xs -> if x > 0 then 1 + (test xs) 
       else test xs;; 

Cập nhật: kể từ khi bạn đã chỉnh sửa để làm rõ vấn đề, sửa đổi mã trên như sau:

let test l = 
    let rec test_helper l pos nonpos = 
    match l with [] -> (pos, nonpos) 
    | x::xs -> if x > 0 then test_helper xs 1+pos, nonpos 
       else test_helper xs pos 1+nonpos 
    in test_helper l 0 0;; 

Sử dụng bộ tích lũy giúp ích rất nhiều trong trường hợp này. Nó cũng làm cho chức năng đuôi đệ quy mà luôn luôn là thực hành tốt.

+0

làm cách nào tôi có thể sửa đổi nó để chuyển tiếp đệ quy ? – REALFREE