Подтвердить что ты не робот

Какова цель "делать!". обозначение в F #?

Я новичок в F #, так что это простой вопрос и, возможно, дубликат, но я не мог найти ответ нигде...

Я читаю эту реализацию LOGO DSL, и я не понимаю, в чем смысл "делать!". обозначение здесь:

    this.Loaded.Add (fun _ ->
        async {
            do! Async.Sleep 200
            for cmd in theDrawing do
                do! this.Execute(cmd)
        } |> Async.StartImmediate 
    )

Вы можете помочь?

4b9b3361

Ответ 1

F # выражения вычислений (a.k.a. "workflows" ) используют синтаксис

builder { expression }

где expression может содержать специальные конструкции, включая различные ключевые слова "bang", такие как let! и do!. Подобно LINQ в С# или VB, выражения вычисления F # представляют собой просто синтаксический сахар (который desugars в вызовы методов на builder).

Одним из наиболее распространенных типов вычислений является async, как описано здесь.

В этом конкретном примере используется async вместе с Async.Sleep, чтобы временно выйти из потока пользовательского интерфейса, чтобы дать UI возможность перерисовать, реагировать на события мыши и т.д. Этот общий метод описан более подробно здесь.

Ответ 2

Я только добавлю, что обозначение do! не должно явно поддерживаться выражением вычисления, потому что то же самое можно записать с помощью let! следующим образом:

do! foo()       // Using do!
let! _ = foo()  // Equivalent using let!

В общем случае let! мы использовали, когда у вас есть функция, реализованная с использованием вычислений, и вы хотите называть ее из другого выражения вычисления того же типа. Это означает, что он используется для составления вычислительных выражений. Для async эта композиция означает, что у вас есть неблокирующий асинхронный код и вызывать его из другого асинхронного рабочего процесса определенным образом, чтобы сделать асинхронный вызов.

Ключевое слово let! позволяет вам сделать это и получить некоторое значение в качестве результата, а do! - это ярлык, который вы можете использовать, если вычисление ничего не возвращает.

Раздел из функционального программирования реального мира, в котором обсуждаются выражения вычислений (а также выражения последовательности), доступен в виде бесплатной выборки, поэтому, если вы хотите прочитать более подробное руководство по выражениям вычисления, это может быть хорошим источником информации:

Кстати: Должна быть возможность написать примерный код в вопросе лучше, используя примитив AwaitEvent, например:

async { 
  let! _ = this.Loaded |> Async.AwaitEvent 
  do! Async.Sleep 200 
  for cmd in theDrawing do 
     do! this.Execute(cmd)  } |> Async.StartImmediate  

Это означает одно и то же: сначала он ждет, пока произойдет событие Loaded, тогда он ждет 200 мс, а затем он выполнит оставшуюся часть работы. Это ожидание является особенным (поэтому мы используем let!/do!, потому что он не блокирует поток при ожидании).

Ответ 3

В этом случае он запускает выражение сна асинхронно, поэтому поток может делать что-то полезное, а не блокировать.

В общем случае let!, use!, yield! и do! выполняют "специальную" обработку содержащихся вычисляющих выражений (что бы это ни было, async в этом случае). Например. в seq { ... } с использованием yield! позволяет подпоследовательность быть объединенной в вывод, а не возвращаться как один объект.