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()

Я бы предпочел что-то вроде этого:

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

спасибо

1 ответов


этот тип подписи выглядит довольно запутанным, когда вы видите его в первый раз, но это имеет смысл.

дизайн библиотеки F#
Идея заключается в том, что когда вы называете PostAndReply вы должны дать ему функции что:

  • создает сообщение типа 'Msg (для отправки агенту)
  • после того, как среда выполнения F# создает канал для отправки сообщений вызывающему абоненту (каналы представлено в виде значений типа AsyncReplyChannel<'Reply>).

сообщение, которое вы создаете, должно содержать канал ответа, но библиотека F# не знает, как вы хотите представить свои сообщения (и поэтому она не знает, как вы хотите сохранить канал ответа в сообщении). В результате библиотека просит вас написать функцию, которая будет создавать сообщение для агента после того, как система построит канал.

ваш вариант предложение
Проблема с вашим предложением заключается в том, что if PostAndReply типа 'Msg -> 'Reply, сообщение, которое агент получает после вызова Receive будет следующего типа:

'Msg * AsyncReplyChannel<'Reply>

... таким образом, каждое сообщение, полученное агенту, также должно было нести канал для отправки ответов. Однако вы, вероятно, не хотите отправлять ответ для каждого полученного сообщения, поэтому это не сработает. Может, тебе что-нибудь понадобится? например:

'Msg * option<AsyncReplyChannel<'Reply>>

... но это только усложняется (и это все еще не совсем правильно, потому что вы можете отвечать только на некоторые сообщения от 'Msg, но не все из них).