2017-10-28 3 views
1

Rosetta Code (source) 섹션에 따르면 OCaml 튜플 (함수로 반환 된 경우)은 활성 상태로 유지되거나 하나의 단위로 수집됩니다. 튜플OCaml 각 요소에 독립적으로 접근 할 수있는 제품 유형

공간 안전은 OCaml의 프로그래머는 여러 값이 튜플로 반환 될 때 이 종결이 는 각각 독립적으로 값을 처리하지 않는 것을 알고 있지만, 전체 튜플을 처리해야한다. 따라서 모든 값이 에 도달 할 수없는 경우에만 모든 값이 확정됩니다.

이 속성이 OCaml 4.05에서 여전히 유효한지, 그리고이 속성이없는 제품 유형의 동일한 기능을 가져 오는 다른 방법이 있는지 궁금합니다.

+0

그레고리, 로제타 코드에 대한 계정을 갖고 있습니까? 언급 한 섹션은 기본적으로 잘못되었으며 적절히 삭제해야합니다. 내 대답을 보라. –

답변

3

저는 OCaml GC에 대한 전문가는 아니지만, 이와 관련하여 상황이 변경되면 매우 놀랐습니다.

Weak module의 약한 배열이 원하는 동작 일 가능성이 있습니다. 약한 포인터 (약 배열)의 배열의

유형 :

여기 유형 'a Weak.t에 대한 개요입니다. 약 포인터는 프로그램에서 값을 더 이상 사용하지 않을 때마다 가비지 수집기가 지울 수있는 값입니다 (일반적인 포인터를 통해).

약한 배열에는 같은 유형의 요소가 있습니다. 다른 유형이 필요한 경우 길이가 1 인 약한 배열의 튜플을 가질 수 있다고 생각합니다. 약한 배열의 값은 독립적으로 가비지 수집됩니다. 그러나 튜플 자체는 모든 배열이 비어있을 때까지 남아 있습니다.

+1

길이가 2 인 약한 배열에 Obj.magic이라는 두 값의 문제가 있는지 (타입 안전성을 보장하기 위해 서명 뒤에 구성을 숨김) 여부를 알고 계십니까? –

+1

저는 개인적으로 이렇게 속임수를 쓰지 않을 것입니다. 그래서 나는 그것을 추천하는 기록에 남기 싫어 :-) –

4

언급 한 텍스트와 예제는 오해의 소지가 있습니다. 튜플과 그 구성 요소는 프로젝트의 구성 요소 중 하나만 프로젝 팅하고 유지하는 경우 프로그램 수명 동안 유지되지 않습니다.

이들은 터플의 구조적 변형의 범위 내에서 최대로 유지 될 것이며, 이들은 일반적으로 수명이 짧다. 저는 개인적으로 그것이 그것이 실제로 문제가되는 것을 결코 발견하지 못했습니다.

let pair a b = 
    let ra = Array.make 1 a 
    and rb = Array.make 1 b in 
    let f r = Printf.printf "> finalised: %d\n%!" r.(0) in 
    Gc.finalise f ra; 
    Gc.finalise f rb; 
    (ra, rb) 

let a = 
    let a, _ = pair 1 2 in 
    let _, _ = pair 3 4 in 
    a 

let() = 
    Gc.full_major(); (* garbage collection *) 
    Printf.printf "Used: %d\n%!" a.(0) 

a 쓰레기 수집 얻을 제외하고 당신은 그 모든 것을 볼 것입니다 : 당신은 약간에 예를 조정할 경우

는 점을 증명합니다. 최상위 정의는 쓰레기가 제대로 일을 수집합니다 :
let e, _ = pair 5 6 
let() = Gc.full_major() 

은 또한 그것은 내가 위에서 설명하는 최악의 시나리오입니다 Leo White 나에게 지적했다. 원래 예제의 a이 표현식에서 두 번 이상 사용되면 다른 구성 요소는 gc'd가됩니다. a을 한 번만 사용하면 실제로 필요할 때까지 OCaml이 튜플에서 투영하지 않습니다. 예를 들어 프로젝션이 if에서 수행되는 경우 프로젝션을 수행 할 필요가 없습니다. 이 최적화는 값의 수명을 연장 할 수는 있지만 원래의 범위를 벗어날 수는 없습니다.

관련 문제