Pergunta

Dado o seguinte:

#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

Como devo ir sobre como resolver isso? Ou devo apenas ir até o aborrecimento de converter "foo" como uma expressão de seqüência?

Foi útil?

Solução

Esta é uma solução, mas eu pessoalmente acho que é o abuso da enquanto a construção.

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

Outras dicas

Outra solução que é ligeiramente melhor na minha opinião. Ela recebe x fora do âmbito cláusula de condição do tempo e coloca-lo em uma y referência que está disponível no âmbito mais elevada. Ainda não é a melhor solução (funcional), mas ele funciona.

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

Eu acho que sua solução rec loop funciona melhor, uma vez que é o mais funcional (evitando efeitos secundários, embora usos foo estatais) e o mais geral (ele funciona em todas as funções ao mesmo tempo que foo). É mais de digitação, mas se você vai usar mais funções como foo, laço é mais produtiva do que a única solução mais curto apenas para foo.

Eu até generalizar ciclo um pouco mais e abstrair a ação do que você quer fazer com um valor em uma situação 'true':

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

loop foo print_any

I como as outras sugestões de como consumir "foo" assumindo foo é mantido fixo.

Para meu nariz, o código para "foo" cheira. Se for razoável para converter "foo" para "bar" ao longo das linhas

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

então eu iria fazê-lo, mas "bar", enquanto um pouco melhor, ainda parece suspeito. (Em "bar", que preservou o aspecto estranho que ele retorna "int ref" em vez de apenas "int", como "foo" fez, mas espero que esse aspecto não foi intencional?)

Eu acho que a única coisa que é tão descolados sobre "foo" é o tipo de informação implícita que não é óbvio a partir do tipo de dados (você pode continuar chamando isso há tanto tempo como a parte bool é verdade), que é o que faz com que o seq versão um pouco mais atraente.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top