F # - mentre la condizione di tupla si affligge
-
03-07-2019 - |
Domanda
Dato quanto segue:
#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
Come devo fare per risolvere questo? O dovrei semplicemente passare attraverso la seccatura per convertire " foo " a un'espressione sequenza?
Soluzione
Questa è una soluzione, ma personalmente penso che sia un abuso della costruzione while.
#light
while
(let (c,x) = foo()
if c then print_any !x
c)
do ()
Altri suggerimenti
Un'altra soluzione che è leggermente migliore secondo me. Ottiene x dall'ambito della clausola condition dell'istante e lo inserisce in un riferimento y che è disponibile nell'ambito superiore. Non è ancora la migliore soluzione (funzionale) ma funziona.
let y = ref 1
while (let (c,x) = foo()
y := !x
c)
do printf "%i" !y
Penso che la tua soluzione rec loop
funzioni meglio poiché è la più funzionale (evitando effetti collaterali, anche se foo usa lo stato) e la più generale (funziona su tutte le funzioni allo stesso tempo come pippo). Digita più a lungo, ma se utilizzerai più funzioni come pippo, il ciclo è più produttivo della soluzione più breve solo per pippo.
Vorrei anche generalizzare un po 'di più e astrarre via l'azione di ciò che vuoi fare con un valore in una situazione "vera":
let loop f a =
let rec loop2() =
match f() with
| (true, x) ->
a x
loop2()
| (false, _) -> ()
loop2()
loop foo print_any
Mi piacciono gli altri suggerimenti su come consumare " foo " supponendo che foo sia tenuto fisso.
Per il mio naso, il codice per " foo " odori. Se è ragionevole convertire " pippo " a "bar" lungo le linee di
let bar =
let x = ref 10
seq {
x := !x - 1
while !x <> 0 do
yield x
x := !x - 1
}
bar |> Seq.iter print_any
allora lo farei, ma "bar", sebbene un po 'meglio, sembra ancora sospetto. (In "barra", ho conservato l'aspetto strano che restituisce "int ref" piuttosto che solo "int", come ha fatto "foo", ma si spera che quell'aspetto fosse involontario?)
Penso che la cosa che è così funky di " foo " è il tipo di informazioni implicite che non è ovvio dal tipo di dati (puoi continuare a chiamarlo fintanto che la porzione bool è vera), che è ciò che rende la versione seq un po 'più attraente.