2012-02-29 12 views
12

cuanto a:MailboxProcessor.PostAndReply opción de diseño

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

No puedo entender por qué la firma se ve tan contrario a la intuición para mí. Lo que queremos hacer es publicar un mensaje a un agente y esperar una respuesta. ¿Por qué tenemos que darle una función extraña como un 'mensaje'?

Véase de nuevo este fragmento de 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() 

prefiero prefieren algo como esto:

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

Gracias

Respuesta

9

Este tipo de firma se ve muy confuso cuando lo ves para el primera vez, pero tiene sentido.

El diseño F # biblioteca
La idea detrás de la es que cuando se llama a PostAndReply que necesita para darle una función que:

  • construye un mensaje de tipo 'Msg (para ser enviado a el agente)
  • después de que F # runtime crea un canal para enviar mensajes a la persona que llama (los canales se representan como valores de tipo AsyncReplyChannel<'Reply>).

El mensaje que construye necesita contener el canal de respuesta, pero la biblioteca F # no sabe cómo quiere representar sus mensajes (y no sabe cómo desea almacenar el canal de respuesta en el mensaje) Como resultado, la biblioteca le pide que escriba una función que construirá el mensaje para el agente después de que el sistema construya el canal.

Su sugerencia alternativa
El problema con su sugerencia es que si PostAndReply tenían un tipo 'Msg -> 'Reply, el mensaje de que el agente recibe después de que se llama Receive sería del siguiente tipo:

'Msg * AsyncReplyChannel<'Reply> 

. .. por lo que cada mensaje recibido por el agente también debería llevar un canal para enviar respuestas. Sin embargo, probablemente no desee enviar una respuesta por cada mensaje recibido, por lo que esto no funcionaría realmente. Tal vez usted podría utilizar algo como:

'Msg * option<AsyncReplyChannel<'Reply>> 

... pero eso es sólo conseguir más complicado (y todavía no esta del todo bien, ya que sólo puede responder a algunos mensajes de 'Msg, pero no a todas ellas)

+0

Ok gracias, ya veo. Si fuera yo, habría requerido en el constructor un parámetro adicional: una función que construye un mensaje de un AsyncReplyChannel ('AsyncReplyChannel <'Reply> -> 'Msg') adicionalmente al cuerpo del agente. De hecho, desde un punto de vista centrado en el usuario, no veo por qué la gente quiere introducir diferentes formas de construir un mensaje de un canal de respuesta, cuando se llama a 'PostAndReply', aunque sería menos genérico. – Okay

+2

@Okay - Eso tampoco funcionaría.Es bastante común tener diferentes formas de construir valores '' Msg' que contienen 'AsyncReplyChannel'. Por ejemplo, el agente de cola de bloqueo (consulte MSDN http://msdn.microsoft.com/en-us/library/hh297096.aspx) tiene dos mensajes diferentes que llevan un canal de respuesta, por lo que tiene dos formas de compilar el mensaje. . Dicho esto, estoy de acuerdo en que la firma es bastante confusa. Sería bueno tener una alternativa más legible, pero no puedo pensar qué podría ser eso ... –

Cuestiones relacionadas