2010-04-16 6 views
19

Soy un principiante en C#, por lo que es una pregunta simple y tal vez un duplicado, pero no pude encontrar la respuesta en cualquier lugar ...¿Cuál es el propósito de "do!" notación en F #?

estoy leyendo this LOGO DSL implementation y no entiendo, lo que es el significado del "¡haz!" notación aquí:

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

¿Me puede ayudar?

Respuesta

7

F # computation expressions (también conocido como "flujos de trabajo") utilizan la sintaxis

builder { expression } 

donde expression pueden contener construcciones especiales, incluyendo las diversas palabras clave "explosión" como let! y do!. Al igual que LINQ en C# o VB, las expresiones de cálculo de F # son simplemente un azúcar sintáctico (que desagua en llamadas de método en el builder).

Uno de los tipos más comunes de expresión de cálculo es async, como se describe here.

En este ejemplo particular, el async se está utilizando junto con Async.Sleep llegar temporalmente el hilo de interfaz de usuario, para dar la interfaz de usuario la oportunidad de volver a dibujar, reaccionar a eventos de ratón, etc. Esta técnica general se describe más here.

3

En su caso, ejecuta la expresión de suspensión de forma asíncrona para que el hilo pueda hacer algo útil en lugar de bloquear.

En general, let!, use!, yield! y do! lo procesan "especial" de las expresiones de cálculo que contienen (sea lo que sea, async en este caso). P.ej. en un seq { ... } usando yield! permite fusionar una subsecuencia en la salida en lugar de devolverla como un solo objeto.

+0

¿Hay un nombre para esta notación? ¿Dónde leer más al respecto? –

+0

"expresiones de cálculo" o "flujos de trabajo"; una explicación antigua (algo desactualizada) está aquí: http://blogs.msdn.com/dsyme/archive/2007/09/22/some-details-on-f-computation-expressions-aka-monadic-or-workflow- syntax.aspx – Brian

+1

Un capítulo de la Programación funcional del mundo real que trata expresiones de cálculo (y también expresiones de secuencia) está disponible como un capítulo de muestra gratis: http://www.manning.com/petricek/SampleChapter12.pdf –

16

voy a añadir solamente que la notación do! no tiene que ser apoyado explícitamente por la expresión de cálculo, porque lo mismo se puede escribir usando let! así:

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

En general let! nosotros utilizamos cuando tiene alguna función implementada usando expresiones de cálculo y quiere llamarla desde otra expresión de cálculo del mismo tipo. Esto significa que se usa para componer expresiones de cálculo. Para async, esta composición significa que tiene un código asincrónico sin bloqueo y lo llama de otro flujo de trabajo asíncrono de alguna manera especial para que la llamada sea asincrónica.

La palabra clave let! le permite hacer esto y obtener algún valor como resultado, mientras que do! es un acceso directo que puede usar si el cálculo no devuelve nada.

un capítulo de la programación funcional del mundo real que trata sobre las expresiones de cálculo (y también las expresiones de secuencia) está disponible como una muestra gratis, así que si quieres leer un tutorial más detallado sobre expresiones de cálculo esto puede ser una buena fuente de infromation:

por cierto: debe ser posible escribir el código de ejemplo en su pregunta de una manera más agradable el uso de la primitiva AwaitEvent así:

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

Esto significa la misma cosa - que espera primero hasta que se produzca el evento Loaded, entonces se espera 200ms y luego lo hace el resto del trabajo. Este espera es especial (es por eso que usamos let!/do!, porque no bloquea el hilo mientras espera).

Cuestiones relacionadas