F # async - разница между двумя структурами - PullRequest
5 голосов
/ 02 августа 2011

Есть ли разница между написанием чего-то вроде этого:

MailboxProcessor.Start(fun inbox -> async {
    let rec loop bugs =
        let! msg = inbox.Receive()
        let res = //something
        loop res
    loop []})

и написанием этого так:

MailboxProcessor.Start(fun inbox ->
    let rec loop bugs = async {
        let! msg = inbox.Receive()
        let res = //something
        do! loop res }
    loop [])

Спасибо!

1 Ответ

7 голосов
/ 02 августа 2011

Первый пример не является допустимым кодом F #, поскольку let! может использоваться только непосредственно внутри выражения вычисления. В вашем примере вы используете его в обычной функции - его тело не является вычислительным выражением, поэтому let! не допускается в этой позиции.

Чтобы сделать его действительным, вам нужно обернуть тело функции loop внутри async:

MailboxProcessor.Start(fun inbox -> async {
    let rec loop bugs = async {
        let! msg = inbox.Receive()
        let res = //something
        return! loop res }
    return! loop []})

Вы также можете сохранить внешний блок async { .. } во фрагменте - тогда вам просто нужно использовать return! для вызова функции loop вместо того, чтобы просто возвращать ее (но, кроме того, нет существенной разницы сейчас ).

Обратите внимание, что я использовал return! вместо do! - это действительно имеет значение, потому что return! представляет хвостовой вызов, что означает, что остальная часть текущего тела может быть отброшена. Если вы используете do!, то асинхронный код выделяет что-то вроде стекового фрейма в куче, поэтому использование do! в рекурсивной циклической функции приводит к потере памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...