2012-02-27 3 views

답변

8

당신이 필수적 스타일에 충실하려는 경우, 당신은 루프 종료 예외를 사용할 수 있습니다


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 

그러나 PPL이 이미 쓴 바와 같이 일반적으로, 기능적인 스타일이 더를 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 

이 예제에서는 두 버전간에 큰 차이가 없지만 exiting 루프/재귀를위한 예외 사용은주의해서 사용해야합니다. 당신은 컨트롤 플로우 버그를 꽤 쉽게 도입 할 수 있으며 때로는 디버그하기가 어렵습니다.

나는 배열의 유효 범위가 항상 위의 예제에 있음을 확신 할 수 있기 때문에 배열 액세스 속도를 높이기 위해 Array.unsafe_get heap i를 사용할 수 있습니다. (아, 우리는하지만, 이외에> = 0 검사를 시작할 필요가 없습니다.)

4

Ocaml의 루프는 필수적이기 때문에 결과를 반환해서는 안됩니다 (단위는 제외). 따라서 단위가 아닌 결과를 반환하려고하면 컴파일러에서 경고를 표시합니다.

Ocaml이 루프에서 결과를 반환하지 못하게하는 이유는 이것이 매우 기능적인 관용어가 아니기 때문입니다. 루프 대신 재귀 함수를 사용하면 일찍 종료하고 결과를 되풀이하는 것이 쉽습니다 (되풀이 대신 결과를 반환). 관용적 인 Ocaml을 작성하려면이 경우 재귀를 사용하는 것이 좋습니다.

5

Takumawa Asumu 맞아, OCaml의 for 루프는 결과를 반환하지 않습니다. 관용적 인 OCaml에서는 재귀를 사용해야합니다. 이상적으로 배열을 위해 작동하는 List.find과 같은 표준 함수가있을 것입니다. OCaml Batteries IncludedBatArray.findi의 기능이있어 원하는 것을 수행합니다.

5

간단하고 효율적인 (아니 전혀 할당) : 필수적 스타일

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) 

또는 :

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 

(미리 계산 된 경우에만 예외로 인해 raise exit이 할당되지 않습니다).

+0

"예외가 미리 계산되었습니다"라는 말은 루프 앞에서'let exit = Exit'를 추가하면 여기에 비효율적 인 것을 방지 할 수 있다는 것입니까? 이것은 최근 OCaml 컴파일러의 경우에도 마찬가지입니까? – anol