2009-05-20 18 views
15

私はちょうどthis pageの情報を読んで、新しい?オペレータが言及されていますが、その使用法は何かわかりません。
誰でも簡単な説明を提供してください。このオペレータをどのように使用し、ユースケースについて言及するかについてのコードを投稿してください。
を編集:これは本当に扱いにくいです。オペレータはDonのリリースノートにはもはや言及されていません。それはなぜなのでしょうか?F#演算子 "?"

答えて

30

二つの新しい "特別な" 演算子は、このF#のリリースであり、かつ(?)(< - ?)。これらは定義されていませんが、オーバーロードが可能であるため、自分で定義することができます。特別なビットは、第2オペランドをどのように扱うかです。有効なF#識別子である必要がありますが、演算子を文字列として実装する関数に渡す必要があります。言い換えれば:

a?b 

に脱糖さ:

(?) a "b" 

と:これらの演算子の非常に単純な定義は

(?<-) a "b" c 

できます

a?b <- c 

がに脱糖されますbe:

let inline (?) (obj: 'a) (propName: string) : 'b = 
    let propInfo = typeof<'a>.GetProperty(propName) 
    propInfo.GetValue(obj, null) :?> 'b 

let inline (?<-) (obj: 'a) (propName: string) (value: 'b) = 
    let propInfo = typeof<'a>.GetProperty(propName) 
    propInfo.SetValue(obj, value, null) 

gettorの戻り値の型がジェネリックであることから、あなたはつまり、ほとんどの場合、使用場所でそれを指定する必要がありますことをご注意:

let name = foo?Name : string 

それでもチェーン・コール(ことができますが? )ジェネリックもある)(の最初の引数(以降?):

let len = foo?Name?Length : int 

もう一つ、もっと面白い、実装は、VBで提供するために再利用CallByNameの方法があります

ことの利点は、DLRを使用して動的なオペレータを実装nuget上など

+1

メモとして、F#PowerPackには妥当なデフォルト実装が含まれているようです。 –

4

"?"演算子は動的言語ランタイム(DLR)に関係します。つまり、コンパイル時ではなく、実行時にオブジェクトメンバ(メソッド、プロパティ)にバインドするときに使用します。

これはC#でも動的メンバー呼び出しがどのように機能するのかと期待して面白かったです。悲しいかな、C#はこの機能を「擬似」タイプ(「ダイナミック」IIRC)で公開しています。私の意見では、これはコードが幾分明確でないことを示しています(呼び出しが早期バインドか遅いバインドかを知るために変数宣言を追跡する必要があるためです)。

正確な構文はわかりませんが、推測しなければならないのであれば、 "。" (ドット)演算子。以下のように:

let x = foo?Bar() 

または多分:

let x = foo.?Bar() 
+1

"コールが早期バインドか遅いバインドかを知るために変数宣言を追跡する必要があるため" ...非常に遠くまで追跡する必要はありません。 dynamicはローカル変数でなければならず、型メンバーにはなれません。変数が動的であるかどうかを調べるために非常に遠くにスクロールする必要がある場合は、リファクタリングする必要があります。さらに、変数の名前の上にマウスを置くと、IDEが喜んでタイプを伝えます。 – Randolpho

+2

良い点。それが価値あるものであれば、「遅延型呼び出し」演算子を「動的」型実装よりも好む別の理由があります。インタフェースを実装することによってDLRにフックすることができるとすれば、同じ参照に対して早期呼び出しと遅い呼び出しをしたいと考えています。 –

+0

fooの型になるべき好奇心から、なぜfoo.Bar()の代わりにそのようにしたいのですか? さらに、リフレクションで同じ結果を得ることはできませんか? – em70

1

モジュールFSharp.Interop.Dynamicがあり、IDispatchのCOMオブジェクトを操作、正しく両方のプロパティとフィールドを処理するということです。

let ex1 = ExpandoObject() in 
ex1?Test<-"Hi"; 
ex1?Test |> should equal "Hi"; 

それはオープンソースですが、Apacheライセンス、あなたはimplementationを見ることができ、それはユニットテストexample casesが含まれています。