スポンサーサイト

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

F#によるデザインパターン入門 Iterator パターン(2) 外部イテレータ(2)ジェネリック

前回は外部イテレータの紹介で次のようなクラスを定義しました。
 
open System.Collections
 
//外部イテレータとして機能するクラス
type MyArrIter(iter_arr : array<int>) =
    let mutable index = -1
    interface IEnumerator with
        member this.MoveNext() =
                if index < iter_arr.Length - 1 then
                    index <- index + 1
                    true
                else
                false 
        member this.Reset() =
                index <- -1
         
        member this.Current =
                iter_arr.[index] :> obj
 
//外部イテレータを発行するクラス
type MyArray (in_array : array<int>) =
    interface IEnumerable with
        member this.GetEnumerator() =
            (new MyArrIter(in_array)) :> IEnumerator
 
 
今回はこれをジェネリックにしてみたいと思います。
 
外部イテレータをIEnumerator<'a>型を実装するようにするのですが、IEnumerator<'a>を実装するには、IEnumeratorとIDisposableを実装する必要があり、その上で、CurrentプロパティのみをIEnumarator<'a>の実装で追加します。
 
> open System
open System.Collections
open System.Collections.Generic;;
 
> type MyGArrIter<'a> (iter_arr : array<'a>) =
    let mutable index = -1
 
    interface IEnumerator<'a>  with
        member this.Current =
                iter_arr.[index] 
 
    interface IEnumerator with
        member this.MoveNext() =
                if index < iter_arr.Length - 1 then
                    index <- index + 1
                    true
                else
                false 
        member this.Reset() =
                index <- -1
         
        member this.Current =
                iter_arr.[index] :> obj
 
    interface IDisposable with
        member this.Dispose() =
            ();;
 
type MyGArrIter<'a> =
  class
    interface IDisposable
    interface IEnumerator
    interface IEnumerator<'a>
    new : iter_arr:'a array -> MyGArrIter<'a>
  end
 
発行側もIEnumerableインターフェイスとIEnumerable<_>インターフェイスの実装が必要となります。
 
> type MyGArray<'a> (in_array : array<'a>) =
    interface IEnumerable<'a> with
        member this.GetEnumerator() =
            (new MyGArrIter<'a> (in_array)) :> IEnumerator<'a>
    interface IEnumerable with
        member this.GetEnumerator() =
            (new MyGArrIter<'a> (in_array)) :> IEnumerator;;
 
type MyGArray<'a> =
  class
    interface IEnumerable
    interface IEnumerable<'a>
    new : in_array:'a array -> MyGArray<'a>
  end
 
 
 
では使ってみます。
最初はstringの配列を保持するものから。
 
> let myStrArr = new MyGArray<string> ([|"a";"bc";"def"|])
let myStrArrIter = (myStrArr :> IEnumerable<string>).GetEnumerator() ;;
 
val myStrArr : MyGArray<string>
val myStrArrIter : IEnumerator<string>
 
> while myStrArrIter.MoveNext() do
    printfn "%s" myStrArrIter.Current;;
a
bc
def
val it : unit = ()
 
次はchar型でやってみます。
 
> let myCharArr = new MyGArray<char> ([|'a';'b';'c'|])
let myCharArrIter = (myCharArr :> IEnumerable<char>).GetEnumerator() ;;
 
val myCharArr : MyGArray<char>
val myCharArrIter : IEnumerator<char>
 
> while myCharArrIter.MoveNext() do
    printfn "%c" myCharArrIter.Current;;
a
b
c
val it : unit = ()
 
前回も紹介しましたが、MyGArray<_>クラスはIEnumerableインターフェイスを実装しているので、for .. in が使えます。

 
> for s in myStrArr do
    printfn "%s" s;;
a
bc
def
val it : unit = ()
 
> for c in myCharArr do
    printfn "%c" c;;
a
b
c
val it : unit = ()
 
ここまで配列を保持したIEnumerable型なクラスを定義してきましたが、一般のarray型はseq型すなわちIEnumerable型なので、外部イテレータを簡単に得ることができます。
 

> let strArr = [|"a";"bc";"def"|]
let strArrIter0 = strArr.GetEnumerator();;
 
val strArr : string [] = [|"a"; "bc"; "def"|]
val strArrIter0 : IEnumerator
 
> strArrIter0.MoveNext();;
val it : bool = true
> strArrIter0.Current;;
val it : obj = "a"
 
上の場合はCurrentでobj型の値が返りますが、次のような外部イテレータを作成するとCurrentでstring型の値が返ります。
 
> let strArrIter1 = (strArr :> IEnumerable<string>).GetEnumerator();;
val strArrIter1 : IEnumerator<string>
 
> strArrIter1.MoveNext();;
val it : bool = true
> strArrIter1.Current;;
val it : string = "a"
 
(備考)ここまで、「外部イテレータ」という言葉を使ってきましたが、一般に.NETでは、「列挙子」という名前が使われるようです。
スポンサーサイト

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

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

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

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

この人とブロともになる

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