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?

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top