スポンサーサイト

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

F#入門編落穂拾い その10 (Indexers のsetter getter)

今回はIndexersの補足としてsetter getterを紹介します。(BLUEPIXYさんにアドバイスしてもらった内容です。)  
 
以前クラス定義の部分でgetterとsetterを次のような例で紹介しました。 
 
type Vec2D (xf : float,yf:float) =  
    let mutable x = xf 
    let mutable y = yf 
     
    member this.ShowContents () 
                = printfn "x = %f y = %f" x y  
                   
    member this.X  
        with get() = x         //getter
        and  set(nx) = x <- nx //setter 
     
    member this.Y = y 
 
実行例
 
> t.X <- 10.0;;  //setter使用
val it : unit = () 
 
> t.X;; 
val it : float = 10.0 //getter使用
 
さてIndexersに関してgetter,setterを定義するには、例えば次のようにします。
(getterだけなら、特に下のように、明示的に定義しなくても、前回のようにも定義できます。)
 

>type myWord (initStr : string) =
    let charArr = initStr.ToCharArray()
    
    member this.ShowContents () 
                = printfn "%s" (new string(charArr))
 
    member this.Item
        with get idx = if idx >= 0 && idx < charArr.Length then
                            Some(charArr.[idx]) 
                       else
                            None //indexが範囲外のときはNoneを返す
        and  set idx c = if idx >= 0 && idx < charArr.Length then
                            charArr.[idx] <- c
                         else
                            () //何もしない;;
                            
type myWord =
  class
    new : initStr:string -> myWord
    member ShowContents : unit -> unit
    member Item : idx:int -> char option with get
    member Item : idx:int -> char with set
  end               
 
実行例
 
> let t = new myWord("Programming C#");;
 
val t : myWord
 
> t.[12];;
val it : char option = Some 'C'
 
> t.[100];;
val it : char option = None
 
> t.[12] <- 'F';;
val it : unit = ()
 
> t.ShowContents();;
Programming F#
val it : unit = ()
 
member this.Itemの部分はifの部分が同じことの繰り返しになっているので、次のようにまとめておいた方が良いと思います。
 
type myWord (initStr : string) =
    let charArr = initStr.ToCharArray()
    let isInRange i = (i >= 0 && i < charArr.Length) 
 
    member this.ShowContents () 
                = printfn "%s" (new string(charArr))
 
    member this.Item
        with get idx = if isInRange idx  then
                            Some(charArr.[idx]) 
                       else
                            None 
        and  set idx c = if isInRange idx then
                            charArr.[idx] <- c
                         else
                            () //何もしない

スポンサーサイト

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

コメントの投稿

非公開コメント

No title

システムからのクラス定義結果表示で、
member Item : idx:int -> char with set
のようになるのはなぜでしょうか?
idx:int -> c:char -> unit
のような感じになるべきのように思いますが・。
バグですかね?
また、set (idx,c) と書いても同様に処理されるようです。

No title

うーん、どうなんでしょうか。私もidx:int -> c:char -> unit であるべきだと思うのですが...

自分でもちょっと調べてみたんですけど、
基本
プロパティのget,setは同じ型で、
setだからと言って、引数の数が変わったり結果の型がunitになったりしない(表示上の話)
Itemメソッドは基本(つまりT'[]に適用する時)
int->T'
ということなんですけど・
まあ、例がちょっと特殊ではありますよね。

No title

「バグではありません。仕様です。」系なのですね。

No title

>「バグではありません。仕様です。」系なのですね。
ですよね、多分。
C#では、getはプロパティの型の値を返すメソッド,setはvoidを返すメソッドと同等ということになっているし、
set は、セットする値を引数ではなくvalue (キーワード)で持つし、
C#では、インデクサはthis[]だし、そこら辺の、.NET との整合と言うことなのかも知れませんね。
(↑勝手に言っているだけですが)
F#では、結局
インデックスの型→get で返す型
インデックスの型→set した型
みたいですね。
set で、p<-v;c とかすると、unit 型でないといけないと怒られるので、set の返す型がunitだということは承知しているみたいですw
プロフィール

T GYOUTEN

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

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

この人とブロともになる

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