2012-02-29 4 views
12

MailboxProcessor.PostAndReplyの設計上の選択

member this.PostAndReply : (AsyncReplyChannel<'Reply> -> 'Msg) * ?int -> 'Reply 

署名が私にはとても直感的に見える理由を私は理解することはできません。私たちがしたいことは、エージェントにメッセージを投稿し、返信を待つことです。 なぜ「メッセージ」として彼に奇妙な機能を与えなければならないのですか?

このMSDNスニペットを再度参照してください:

let rec loop() = 
    printf "> " 
    let input = Console.ReadLine() 
    printThreadId("Console loop") 
    let reply = agent.PostAndReply(fun replyChannel -> input, replyChannel) 
    if (reply <> "Stopping.") then 
     printfn "Reply: %s" reply 
     loop() 
    else 
     () 
loop() 

私はむしろこのような何かを好むだろう:あなたはそれを見たときのおかげ

答えて

9

この型シグネチャはかなり混乱に見えます

member this.PostAndReply : 'Msg * ?int -> 'Reply 

を初めてですが、それは理にかなっています。

F#ライブラリの設計
の背後にある考え方は、あなたがPostAndReply呼び出すときにそれを機能与える必要があるということです。

  • がに送られるタイプ'Msg(のメッセージを作成しますエージェント)
  • F#ランタイムが発信者にメッセージを返すためのチャネルを作成した後(チャネルはタイプAsyncReplyChannel<'Reply>の値として表されます)。

あなたが構築するメッセージには返信チャネルが必要ですが、F#ライブラリはメッセージの表現方法がわからないため(メッセージに返信チャネルをどのように保存するか分かりません) )。結果として、ライブラリーは、システムがチャネルを構築した後にエージェントのメッセージを構成する関数を記述するように求めます。

'Msg * AsyncReplyChannel<'Reply> 

あなたの代わりの提案
あなたの問題がある場合は、PostAndReplyはタイプ'Msg -> 'Replyを持っていたならば、それはReceiveを呼び出した後にエージェントが受信したメッセージは、次のタイプであろうということです。 ..エージェントに受け取られたすべてのメッセージは、返信を返すためのチャネルも運ばなければなりません。しかし、おそらく受信したメッセージごとに返信を送り返したくないので、実際にはうまくいかないでしょう。たぶん、あなたのようなもの使用することができます

'Msg * option<AsyncReplyChannel<'Reply>> 

を...それはちょうどより複雑になってきた(とあなただけ'Msgからではなく、それらのすべてにいくつかのメッセージに返信することができますので、それはまだ、かなり右ではありません)。

+0

ありがとうございます。それが私の場合は、コンストラクタ内に、AsyncReplyChannel( 'AsyncReplyChannel <'Reply> - > 'Msg')からエージェント本体にメッセージを構成する追加のパラメータが必要でした。確かに、ユーザ中心の観点から、私は 'PostAndReply'を呼び出すときに返信チャンネルからmsgを構築するためにさまざまな方法を導入したいのですが、それは一般的ではありません。 – Okay

+2

@おかず - それはうまくいかないでしょう。'AsyncReplyChannel'を含む' 'Msg'値を構築する方法はいろいろあります。たとえば、ブロッキングキューエージェント(MSDN http://msdn.microsoft.com/en-us/library/hh297096.aspx参照)には、応答チャネルを持つ2つの異なるメッセージがあり、メッセージを構成する方法は2つあります。 しかし、私は署名がかなり混乱していることに同意します。読みやすい選択肢があるのはいいですが、私はそれが何であるか考えることはできません... –