2012-02-27 3 views

Trả lời

8

Nếu bạn muốn gắn bó với phong cách bắt buộc, bạn có thể sử dụng một ngoại lệ để thoát khỏi vòng lặp:


exception Found of int 

let find_free_next heap start = 
    try 
    for i = start to Array.length heap - 1 do 
     match heap.(i) with 
     | Hdr (Free (h), g) -> raise (Found i) 
     | _ ->() (* If it is not what you are seeking *) 
    done; 
    raise Not_found 
    with 
    | Found n -> n 

Nhưng nói chung, như ppl đã viết, phong cách chức năng là hơn ưa thích trong OCaml:


let find_free_next heap start = 
    let len = Array.length heap in 
    let rec find i = 
    if i >= len then None 
    else 
     match heap.(i) with 
     | Hdr (Free h, g) -> Some i 
     | _ -> find (i+1) 
    in 
    find start 

Trong ví dụ này, không có nhiều khác biệt giữa hai phiên bản, nhưng việc sử dụng ngoại lệ cho các vòng lặp/thu thập phải được sử dụng cẩn thận; bạn có thể giới thiệu các lỗi luồng kiểm soát khá dễ dàng với chúng và đôi khi chúng khó gỡ lỗi.

BTW, bạn có thể sử dụng Array.unsafe_get heap i để tăng tốc độ truy cập mảng của bạn vì bạn có thể chắc chắn rằng tôi luôn nằm trong phạm vi hợp lệ của mảng các ví dụ trên. (Oh, chúng ta cần bắt đầu> = 0 check in Ngoài ra, mặc dù.)

4

Vòng trong Ocaml được cho là bắt buộc, vì vậy nó không nên trả lại kết quả (ngoài đơn vị). Vì vậy, nếu bạn cố gắng trả về kết quả không phải đơn vị, trình biên dịch sẽ đưa ra một cảnh báo.

Lý do khiến Ocaml không cho phép bạn trả lại kết quả từ vòng lặp là vì đây không phải là thành ngữ rất chức năng. Nếu bạn sử dụng hàm đệ quy thay vì vòng lặp, thật dễ dàng để thoát sớm và trả lại kết quả (bằng cách trả về kết quả thay vì định kỳ). Nếu bạn muốn viết Ocaml thành ngữ, bạn có thể muốn sử dụng đệ quy trong trường hợp này.

5

Asumu Takikawa là đúng, vòng lặp for trong OCaml không trả lại kết quả. Trong OCaml thành ngữ, bạn nên sử dụng đệ quy để thay thế. Lý tưởng nhất là sẽ có một chức năng tiêu chuẩn như List.find hoạt động cho các mảng. Có một chức năng BatArray.findi trong OCaml Batteries Included làm những gì bạn muốn.

5

đơn giản hơn, và hiệu quả hơn (không phân bổ ở tất cả):

let rec find_free_next heap start = 
    if start = Array.length heap then raise Not_found; 
    match heap.(i) with 
    | Hdr (Free h, g) -> i 
    | _ -> find_free_start heap (i+1) 

Hoặc, trong phong cách bắt buộc:

let exit = Exit 
let find_free_next heap start = 
    let pos = ref (-1) in 
    try 
    for i = start to Array.length heap - 1 do 
     match heap.(i) with 
     | Hdr (Free h, g) -> pos := i; raise exit 
     | _ ->() 
    done; 
    raise Not_found 
    with Exit -> !pos 

(thông báo rằng raise exit không chỉ phân bổ vì ngoại lệ nếu được tính trước).

+0

Bởi "ngoại lệ được precomputed", bạn có nghĩa là thêm 'let exit = Exit' trước khi vòng lặp là những gì ngăn ngừa một số không hiệu quả ở đây? Điều này vẫn sẽ là trường hợp với một trình biên dịch OCaml gần đây? – anol