F # - enquanto desgraças determinada condição tupla
-
03-07-2019 - |
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?
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.