Первый пример не является допустимым кодом 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!
в рекурсивной циклической функции приводит к потере памяти.