2012-09-15 5 views
2

OCaml Format 모듈을 F #으로 변환하고 OCaml Pervasives at_exit을 사용하여 문제를 다시 추적했습니다. OCaml을 F #로 변환 : F # Equivelent of Pervasives at_exit

val at_exit : (unit -> unit) -> unit 

는 프로그램 종료시 호출 될 주어진 함수를 등록합니다. at_exit으로 등록 된 함수는 프로그램이 exit를 실행하거나 종료 될 때 정상적으로 또는 캐치되지 않는 예외로 인해 호출됩니다. 이 함수는 "최후의 선착순"순서로 호출됩니다. 가장 최근에 at_exit을 추가 한 함수가 먼저 호출됩니다.

변환 과정에서 필자는 컴파일러가 필요하지 않은 것으로 플래그를 지정하지 않았기 때문에 코드에서 이벤트를 예상하지 못했습니다.

at_exit에 대해 FSharp.PowerPack.Compatibility.PervasivesModule을 확인했으며 VS 개체 브라우저를 사용하여 찾을 수 없습니다. OCaml의 코드의 디버그 세션 동안 그것의 사용에서 찾고 또한 val print_flush : (unit -> unit)

:

은 내가 OCaml의 라인 print_flush 서명

at_exit print_flush 

입니다 how to run code "at_exit"?How do I write an exit handler for an F# application?

을 찾았어요 , at_exit은 초기화가 끝날 때와 모듈 호출을 사용할 때마다 호출됩니다.

제안 방법에 대한 의견이 있습니다. 이것은 F #에서의 첫 번째 행사가 될 것입니다.

편집 여기

내가 문제에 도움이 되거해야하는 형식 모듈에 대해 배운 내용 중 일부입니다.

형식 모듈은 int, bool, string과 같은 간단한 OCaml 값의 기본 예쁜 프린터 명령에 대한 함수 라이브러리입니다. 형식 모듈은 print_string과 같은 명령을 가지고 있지만, 다음 행을 경계 상자에 넣고, 왼쪽 및 오른쪽 여백의 새로운 세트를 생각하는 명령도 있습니다. 같은 open_boxprint_string

print_string "Hello" 

또는

open_box 0; print_string "<<"; 
open_box 0; print_string "p \/ q ==> r"; close_box(); 
print_string ">>"; close_box() 

명령은 명령을 해석 루프에 의해 처리 된 후 현재 행 또는 사전에 인쇄 시들어 결정 : 그래서 하나를 쓸 수 다음 줄. 명령은 대기열에 보관되며 왼쪽 및 오른쪽 여백과 같은 변경 가능한 값을 저장하는 상태 레코드가 있습니다.

OCaml 코드 작업에 대한 테스트 케이스 디버깅에서 모듈의 초기화가 끝난 후 첫 번째 호출이 Format 모듈의 모든 함수에 적용되기 전에 대기열과 상태를 준비해야합니다. 형식 모듈에 대한 최초 호출에 대해 마지막으로 일치하는 프레임이 제거 된 at_exit에 대한 메커니즘을 사용하여 대기열과 상태가 정리되고 다음 명령 세트에 대해 다시 채워 지므로 at_exit에 대한 호출이 실행됩니다 나머지 명령을 큐에 넣고 큐와 상태를 다시 초기화합니다.

따라서 print_flush에 대한 호출 순서는 매우 중요하며 OCaml 설명서의 내용보다 많은 것으로 보입니다. 그것을 테스트

module Pervasives = 
    open System 
    open System.Threading 

    // 
    let mutable private exitFunctions : (unit -> unit) list = List.empty 

    // 
    let mutable private exitFunctionsExecutedFlag = 0 

    // 
    let private tryExecuteExitFunctions _ = 
     if Interlocked.CompareExchange (&exitFunctionsExecutedFlag, 1, 0) = 0 then 
      // Run the exit functions in last-in-first-out order. 
      exitFunctions 
      |> List.iter (fun f -> f()) 

    // Register handlers for events which fire when the process exits cleanly 
    // or due to an exception being thrown. 
    do 
     AppDomain.CurrentDomain.ProcessExit.Add tryExecuteExitFunctions 
     AppDomain.CurrentDomain.UnhandledException.Add tryExecuteExitFunctions 

    // 
    let at_exit f = 
     // TODO : This function should be re-written using atomic operations 
     // for thread-safety! 
     exitFunctions <- f :: exitFunctions 

그리고 몇 가지 코드를 :

+1

당신은 당신의 main 메소드 내부 –

+0

또 다른 아이디어를'finally'를 둘 수 있었다 - 하나에 개최 형식의 인스턴스를 만들고 소멸자가 프로그램을 종료 할 때 호출하도록하십시오. –

답변

1

이 그것을해야

open System 

// Register a couple of handlers to test our code. 
Pervasives.at_exit <| fun() -> 
    Console.WriteLine "The first registered function has fired!" 

Pervasives.at_exit <| fun() -> 
    Console.WriteLine "The second registered function has fired!" 
    TimeSpan.FromSeconds 1.0 
    |> System.Threading.Thread.Sleep 
    Console.WriteLine "Exiting the second registered function!" 

Pervasives.at_exit <| fun() -> 
    Console.WriteLine "The third registered function has fired!" 

// Do some stuff in our program 
printfn "blah" 
printfn "foo" 
printfn "bar" 

(* The functions we registered with at_exit should be fired here. *) 

// Uncomment this to see that our handlers work even when the 
// program crashes due to an unhandled exception. 
//failwith "Uh oh!" 
+0

아직이 답변을 테스트하지는 않았지만 일단 결과를 게시 할 것입니다. :) –