「プログラミング in OCaml」をF#で(5)
第七章例外処理。意外と普通。というか、他の言語でも、例外の型で処理を振り分ける仕組みが見た目パターンマッチングっぽい。練習問題も少ない……。
- P145。fsi.exe(F#の対話実行環境)だと、raiseした時の出力が全然違う。どういう意味なのかわからない……。
> raise Not_found;; stdin(0,0): error: FS0030: Value restriction. Type inference has inferred the signature val it : '_a Either define 'it' as a simple data term, make it a function, or add a type constraint to instantiate the type parameters.
- P145。例外周りはOCamlと結構違うらしく、FS0062警告が出まくり。Division_by_zero > System.DivideByZeroException、Invalid_argument > InvalidArgument などなど。
- P146。findの実行結果なんか変なので調べたら、Not_foundの実体はSystem.IndexOutOfRangeExceptionみたいだった。それなら、Division_by_zeroの代わりにSystem.DivideByZeroExceptionを使え、というのと同様の警告が出ても良さそうだけど……
- 上の件。Invalid_argument > InvalidArgumentは、字面が違うだけで、同じように使える。
> InvalidArgument "0";; val it : exn = InvalidArgumentException ()
- しかし、Division_by_zero > System.DivideByZeroExceptionはそうではない。System.DivideByZeroException;;にすると、型名だかコンストラクタだかの使い方がおかしいので、newをつけろ、みたいなエラーが出る。newをつけると同じ感じになる。同じ感じでもないか……。まぁでもraiseできる。
> new System.DivideByZeroException();; val it : System.DivideByZeroException = System.DivideByZeroException: 0 で除算しようとしました。 {Data = dict []; HelpLink = null; InnerException = null; Message = "0 で除算しようとしました。"; Source = null; StackTrace = null; TargetSite = null;}
- InvalidArgumentExceptionのコンストラクタにはF#の例外コンストラクタであるInvalidArgumentが割り当てられているけど、System.DivideByZeroExceptionのコンストラクタにはF#の例外コンストラクタが割り当てられていない、ような感じに見えるんだけど、どうなんだろうか。ついでに、raise (new System.DivideByZeroException()) とかした時のcatchの仕方がわからない……
- sampleディレクトリを漁っていたら、
with | :? Sockets.SocketException | :? System.IO.IOException ->
- こんな感じで、判別できるみたいだった。
- 練習問題は全部できたと思うので省略
- 追記:prim-types.fsをみてたら
[<ReflectedDefinition>] let failwith s = raise (Failure(s)) [<ReflectedDefinition>] let invalid_arg s = raise (InvalidArgument(s)) [<ReflectedDefinition>] let invalid_op s = raise (System.InvalidOperationException(s)) [<ReflectedDefinition>] let not_found() = raise (new System.IndexOutOfRangeException())
- prim-types.fsiに
// F#-specific Exceptions exception Failure of string exception InvalidArgument of string exception AssertionFailure of string * int * int exception MatchFailure of string * int * int
/// Throw a 'FailureException' exception val failwith : string -> 'a /// Throw an 'InvalidArgumentException' exception val invalid_arg : string -> 'a /// Throw an 'InvalidOperationException' exception val invalid_op : string -> 'a /// Throw an 'IndexOutOfRangeException' exception val not_found : unit -> 'a
- とか書いてあったので、まぁなんかよくわからないけど、これらが特別に設定してあるということなんだろうな、と理解した。