2012-02-29 13 views
12

Patrząc na:MailboxProcessor.PostAndReply wybór projektu

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

Nie mogę zrozumieć, dlaczego podpis wygląda tak intuicyjne do mnie. Chcemy wysłać wiadomość do agenta i czekać na odpowiedź. Dlaczego musimy dać mu dziwną funkcję "wiadomości"?

Zobacz kolejny fragment tej 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() 

Wolałbym wolą coś takiego:

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

Thanks

Odpowiedz

9

Podpis ten typ wygląda dość kłopotliwe, gdy widzisz to dla po raz pierwszy, ale ma to sens.

Konstrukcja F # biblioteka
Ideą jest to, że podczas rozmowy PostAndReply trzeba dać mu funkcję że:

  • konstruuje komunikat typu 'Msg (należy przesłać do agent)
  • po uruchomieniu F # runtime tworzy kanał do wysyłania wiadomości z powrotem do osoby dzwoniącej (kanały są reprezentowane jako wartości typu AsyncReplyChannel<'Reply>).

Wiadomość, którą tworzysz musi zawierać kanał odpowiedzi, ale biblioteka F # nie wie, w jaki sposób chcesz reprezentować twoje wiadomości (i dlatego nie wie, w jaki sposób chcesz zapisać kanał odpowiedzi w wiadomości). W rezultacie biblioteka prosi o napisanie funkcji, która skonstruuje komunikat dla agenta po tym, jak system skonstruuje kanał.

Twoja alternatywa propozycja
Problem z sugestią, że jeśli PostAndReply miał rodzajem 'Msg -> 'Reply, wiadomość, że agent otrzymuje po wywołuje Receive będzie z następujących kategorii:

'Msg * AsyncReplyChannel<'Reply> 

. .. więc każda wiadomość otrzymana do agenta będzie również musiała mieć kanał do wysyłania odpowiedzi z powrotem. Jednak prawdopodobnie nie chcesz wysyłać odpowiedzi z powrotem na każdą otrzymaną wiadomość, więc to by nie zadziałało. Być może można użyć coś takiego:

'Msg * option<AsyncReplyChannel<'Reply>> 

... ale to po prostu coraz bardziej skomplikowane (i nadal nie jest całkiem w porządku, bo można odpowiadać tylko do niektórych komunikatów z 'Msg, ale nie wszystkie z nich).

+0

Ok dzięki, widzę. Gdyby to było ja, potrzebowałbym w konstruktorze dodatkowego parametru: funkcji, która konstruuje wiadomość z AsyncReplyChannel ('AsyncReplyChannel <'Reply> -> 'Msg') dodatkowo do ciała agenta. Rzeczywiście, z punktu widzenia użytkownika, nie rozumiem, dlaczego ludzie chcieliby wprowadzić różne sposoby budowania msg z kanału odpowiedzi, podczas wywoływania 'PostAndReply', choć byłoby to mniej ogólne. – Okay

+2

@Okay - To też nie działa.Często zdarza się, że mają różne sposoby konstruowania wartości '' Msg', które zawierają 'AsyncReplyChannel'. Na przykład agent kolejki blokującej (zobacz MSDN http://msdn.microsoft.com/en-us/library/hh297096.aspx) ma dwa różne komunikaty, które przenoszą kanał odpowiedzi, więc masz dwa sposoby na utworzenie wiadomości . To powiedziawszy, zgadzam się, że podpis jest dość zagmatwany. Byłoby miło mieć bardziej czytelną alternatywę, ale po prostu nie mogę pomyśleć, co to może być ... –