Let's begin F#
Let's begin F#
Let's begin F#
ATOMRSS
部屋に参加

トピック:try .. with .. finally

masaito5

try構文でwithとfinallyの両立はできるのでしょうか?

try e1 with rulesとtry e1 finally e2 はThe F# Programming Language Informal Specificationに載ってますが、両立しないように見えます。両方指定するとコンパイルエラーになります。Foundations of F#を見ると、両方指定できるように書いてあるのですが...

  • アクセス数:380件
  • コメント数:4件
  • codeなにがしブックマークに追加する 0 users
  • このページを del.icio.us に追加
  • このページをはてなブックマークに追加

コメント

ソースなしのオレオレ解釈ですが。。

http://research.microsoft.com/fsharp/manual/spec2.aspx#_T...

Draft にも、Try-catch Expressions と Try-finally Expressions で別々の項が設けられていて、Try-catch-finally Expressions という項はありませんね。そして、実際に両方指定してコンパイルするとエラーになる。ならば、そういう書き方はできないのでしょう。
やるのならネストですね。

> try
-   try
-     failwith "exception"
-   with
-     e -> printfn "Catch - %s" e.Message
- finally
-   printfn "Finally";;
Catch - exception
Finally
val it : unit = ()
Don Syme の意図としては、「F# は既に use(C# でいうところの using 構文)を持ってるんだから、可能な限りそっちを使ってね」ってことなのかなーとか思ったり。

GJGJGJGJ

ありがとうございました。まだ、use構文は知らないのでこれから勉強します。

  • GoodJob
  • 0

IDisposable なクラスのインスタンスを変数に束縛する場合、let でなく use を使うことができます。

http://research.microsoft.com/fsharp/manual/spec2.aspx#_T...

open System.IO;;

let read_first_line(file) =
    use reader = new StreamReader(File.OpenRead(file)) in
    reader.ReadLine();;
これは次のコードと等価です。
open System.IO;;

let read_first_line(file) =
    let reader = new StreamReader(File.OpenRead(file)) in
    try
      reader.ReadLine()
    finally
      ( match (reader :> obj) with
          null -> ()
        | _    -> (reader :> System.IDisposable).Dispose() );;
.NET Framework において、アンマネージ リソース(外部リソース)を扱うクラスは、たいていの場合 IDisposable インターフェースを実装していますから(すべてがそうであるかは知らないです)、ほとんどの場合において、finally 句が必要なコードを use によって書き換えることは妥当です。
open System.IO;;

let read_first_line_byUse(file) =
    use reader = new StreamReader(File.OpenRead(file)) in
    try
      reader.ReadLine()
    with
      e -> failwith "IO error!";;

let read_first_line_byFinally(file) =
    let reader = new StreamReader(File.OpenRead(file)) in
    try
      try
        reader.ReadLine()
      with
        e -> failwith "IO error!"
    finally
      ( match (reader :> obj) with
          null -> ()
        | _    -> (reader :> System.IDisposable).Dispose() );;
「アンマネージ リソースを扱うのに IDisposable を実装していないクラス」を扱う場合には、finally が必要になりますね。たとえば、COM オブジェクトを扱うコードでは、finally 句で ReleaseComObject しなければならない、とか。

GJGJGJGJ

おお、丁寧な解説に心から感謝します!

関数型言語についてはある程度の前提知識があるので、F#の言語仕様にはいまのところ理解しがたいところはありませんが、.Netについてはなんの知識もありません。@ITの記事なども読んで勉強していくつもりですが、いげ太さんの解説はとても有益でした。有難うございます。

  • GoodJob
  • 0

前へ 1 次へ

コメントする

[block]から[/block]までの範囲はブロック表示されます。
部分的に目立たせたい時や、引用などにお使いください。

[code]から[/code]までの範囲は等幅表示されます。
ソースコードや設定ファイルの記述などにお使いください。

コメントする権限がありません