Pregunta

Teniendo en cuenta lo siguiente:

#light
//any function returning bool * 'a
let foo =
    let x = ref 10
    fun () ->
        x := !x - 1
        if !x <> 0 then
            (true, x)
        else
            (false, x)

while let (c,x) = foo() in c do print_any x;//can't access x, but would be convinent.

//this is how I want it to work, without all the typing
let rec loop f =
    match f() with
    | (true, x) ->
        print_any x
        loop f
    | (false, _) -> ()
loop foo

¿Cómo debo resolver esto? O debería simplemente pasar por la molestia de convertir " foo " a una expresión de secuencia?

¿Fue útil?

Solución

Esta es una solución, pero personalmente creo que es un abuso de la construcción del momento.

#light
while 
   (let (c,x) = foo()
    if c then print_any !x
    c)
   do ()

Otros consejos

Otra solución que es un poco mejor en mi opinión. Obtiene x fuera del alcance de la cláusula de condición del tiempo y lo coloca en una referencia y que está disponible en el alcance superior. Aún no es la mejor solución (funcional) pero funciona.

let y = ref 1
while (let (c,x) = foo()
       y := !x
       c)
       do printf "%i" !y

Creo que su solución rec loop funciona mejor ya que es la más funcional (evita los efectos secundarios, aunque foo usa el estado) y la más general (funciona en todas las funciones del mismo tiempo) como foo). Es más largo escribir, pero si usará más funciones como foo, loop es más productivo que la única solución más corta solo para foo.

Incluso me gustaría generalizar un poco más y abstraer la acción de lo que quieres hacer con un valor en una situación "verdadera":

let loop f a = 
   let rec loop2() = 
      match f() with
      | (true, x) ->
         a x
         loop2()
      | (false, _) -> ()
   loop2()

loop foo print_any

Me gustan las otras sugerencias sobre cómo consumir " foo " asumiendo que foo se mantiene fijo.

Para mi nariz, el código de " foo " huele Si es razonable convertir " foo " a " barra " a lo largo de las líneas de

let bar =    
    let x = ref 10    
    seq {
        x := !x - 1        
        while !x <> 0 do
            yield x
            x := !x - 1        
    }
bar |> Seq.iter print_any

entonces lo haría, pero " bar " ;, aunque algo mejor, todavía parece sospechoso. (En "barra", conservé el aspecto extraño que devuelve "int ref" en lugar de solo "int", como lo hizo foo, pero espero que ese aspecto no haya sido intencional).

Creo que lo que es tan funky sobre " foo " es el tipo de información implícita que no es obvia a partir del tipo de datos (puede seguir llamándolo siempre y cuando la porción bool sea cierta), que es lo que hace que la versión seq sea un poco más atractiva.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top