スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#によるLinq to Obj入門 (13) ToList ToArray

ToList,ToArrayはF#では、seq型をList,arrayに変換します。
 
> (seq[1;2;3]).ToList();;
val it : List<int> = seq [1; 2; 3]
 
> (seq[1;2;3]).ToArray();;
val it : int [] = [|1; 2; 3|]
 
この機会に遅延評価について復習しておきたいとおもいます。
まずmySeqを次の様に定義します。
 
> let mySeq = seq{ do printfn "1を産出します。"
                 yield 1
                 do printfn "2を産出します。"
                 yield 2
                 printfn "3を産出します。" //doはなくてもよい
                 yield 3
                 printfn "4を産出します。"
                 yield 4
                 printfn "5を産出します。"
                 yield 5 };;
 
val mySeq : seq<int>
 
遅延評価なので、見ての通り"1を産出します。"などは表示されません。
 
> mySeq.Take (3);;
1を産出します。
2を産出します。
3を産出します。
val it : seq<int> = seq [1; 2; 3]
 
このように3個要素を取ってくると、三個とるまでの部分が実行評価されます。
 
> mySeq.Take (2);;
1を産出します。
2を産出します。
val it : seq<int> = seq [1; 2]
 
今度は2個要素を取ってくると、また最初から評価がはじまり、二個とるまでの部分が実行評価されます。
 
ということで何度もmySeqを使いたい場合は、list,array化しておくという手法がよくとられます。
 
> let myList = mySeq.ToList();;
1を産出します。
2を産出します。
3を産出します。
4を産出します。
5を産出します。
 
val myList : List<int>
 
> let myArray = mySeq.ToArray();;
1を産出します。
2を産出します。
3を産出します。
4を産出します。
5を産出します。
 
val myArray : int [] = [|1; 2; 3; 4; 5|]
 
まあ最初からそうすることが決まっている場合は
 
let myList0 = [  do printfn "1を産出します。"
                 yield 1
                 ......
                 yield 5 ]
 
とか
 
let myArray0 = [| do printfn "1を産出します。"
                  yield 1
                  ......
                  yield 5 |]
                  
とかします。
 
なお、シークエンスにはキャッシュ機能をつけることもできます。例えば
 
> let cacheMySeq = Seq.cache mySeq;;
val cacheMySeq : seq<int>
 
としておけば
 
> Seq.take (2) cacheMySeq;;
1を産出します。
2を産出します。
val it : seq<int> = seq [1; 2]
 
> Seq.take (5) cacheMySeq;;
3を産出します。
4を産出します。
5を産出します。
val it : seq<int> = seq [1; 2; 3; 4; ...]
 
となり、同じ部分を2度計算することがなくなります。
 
なお遅延評価は例外を処理するときにも注意が必要です。
 
次のような関数を定義します。
 
> let myTest() =
    
    let mutable failSeq = seq[]
    try
        failSeq <-
            seq{  do printfn "1を産出します。"
                  yield 1
                  failwith "失敗しました"
                  yield 2
                 }
        printfn "tryを抜けます"
    
    with 
    | ex -> printfn "type = %A  mes = %A " (ex.GetType ()) ex.Message
    
    Seq.iter (fun x -> printf "%d :" x) failSeq;;
 
val myTest : unit -> unit
 
実行してみます。
 
> myTest();;
tryを抜けます
1を産出します。
System.Exception: 失敗しました
   場所 FSI_0037.myTest@11.GenerateNext(IEnumerable`1& next)
   場所 Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1.MoveNextImpl()
   場所 Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase`1.System-Collections-IEnumerator-MoveNext()
   場所 Microsoft.FSharp.Collections.SeqModule.Iterate[T](FSharpFunc`2 action, IEnumerable`1 source)
   場所 <StartupCode$FSI_0038>.$FSI_0038.main@()
エラーのため停止しました
 
ということで例外を補足できていません。
これは実際にシークエンスが生成されるのが
 
Seq.iter (fun x -> printf "%d :" x) failSeq
 
の場所だからです。
 
次の様に直します。
 
> let myTest() =
    
    let mutable failSeq = seq[]
    failSeq <-
            seq{  do printfn "1を産出します。"
                  yield 1
                  failwith "失敗しました"
                  yield 2
                 }
 
    try   
        Seq.iter (fun x -> printf "%d :" x) failSeq
    with 
    | ex -> printfn "type = %A  mes = %A " (ex.GetType ()) ex.Message
;;
 
val myTest : unit -> unit
 
実行します。
 
> myTest();;
 
1を産出します。
1 :type = System.Exception  mes = "失敗しました" 
val it : unit = ()
 
ということで今回は例外をcatchできました。
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。