Frage

Bei den folgenden:

#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

Wie soll ich tun, um diese zu lösen? Oder soll ich einfach durch den Aufwand „foo“ zu einer Sequenz Ausdruck zu konvertieren?

War es hilfreich?

Lösung

Dies ist eine Lösung, aber ich persönlich denke, es Missbrauch der während Konstruktion ist.

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

Andere Tipps

Eine andere Lösung, die etwas meiner Meinung nach besser ist. Es wird x aus dem Bedingungsklausel Umfang der während und legt sie in einer Referenz-y, die im höheren Umfang zur Verfügung steht. Immer noch nicht die beste (funktionale) Lösung, aber es funktioniert.

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

Ich denke, Ihre rec loop Lösung am besten funktioniert, da es die meisten funktionalen ist (Vermeidung von Nebenwirkungen, obwohl foo Zustand verwendet) und die allgemeinste (es funktioniert auf alle Funktionen der gleichen Zeit wie foo). Es ist mehr schreiben, aber wenn Sie mehr Funktionen wie foo verwenden, Schleife ist produktiver als die einzige kürzeste Lösung nur für foo.

Ich würde verallgemeinern noch einige weitere Schleife und abstrahieren die Aktion von dem, was Sie wollen, mit einem Wert in einer ‚wahren‘ Situation zu tun:

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

loop foo print_any

Ich mag die anderen Vorschläge, wie „foo“ zu konsumieren, unter der Annahme, foo befestigt gehalten wird.

Zu meiner Nase, der Code für "foo" riecht. Wenn es vernünftig „foo“ zu „bar“ nach dem Vorbild der

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

, dann würde ich es tun, aber „bar“, während etwas besser, noch fischig scheint. (In „bar“, ich erhielt den ungeraden Aspekt, dass es „int ref“ und nicht nur „int“, als „foo“ zurück tat, aber hoffentlich, dass Aspekt war unbeabsichtigt?)

Ich denke, die Sache, die so funky über „foo“ ist, ist die Art von impliziten Informationen, die von dem Datentyp nicht offensichtlich ist (Sie halten diese so lange telefonieren wie der Boolesche Teil wahr ist), das ist, was die seq macht Version ein wenig attraktiver zu machen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top