質問

次の場合:

#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

これを解決するにはどうすればよいですか? または、「foo」を変換するために手間をかける必要がありますか?シーケンス式へ?

役に立ちましたか?

解決

これは1つの解決策ですが、個人的にはwhile構造の乱用だと思います。

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

他のヒント

私の意見ではもう少し良い別の解決策。 whileのcondition句スコープからxを取得し、それを上位yスコープで使用可能な参照yに入れます。それでも最良の(機能的な)ソリューションではありませんが、動作します。

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

rec loop のソリューションは、最も機能的なもの(fooは状態を使用しますが副作用を回避)および最も一般的なもの(同時にすべての機能で機能する) fooとして)。入力は長くなりますが、fooのような関数をさらに使用する場合は、fooの単一の最短ソリューションよりもループの方が生産的です。

ループをさらに一般化し、「true」の状況で値を使用して実行するアクションを抽象化します。

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

loop foo print_any

&quot; foo&quot;の消費方法に関する他の提案が好きです。 fooが固定されていると仮定します。

私の鼻には、&quot; foo&quot;のコードにおいがする。 &quot; foo&quot;を変換するのが妥当な場合「バー」への線に沿って

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

その後、私はそれを行いますが、「バー」は多少良くなりますが、まだ怪しいようです。 (&quot; bar&quot;では、&quot; foo&quot;のように、単なる&quot; int&quot;ではなく、&quot; int ref&quot;を返すという奇妙な側面を保存しましたが、願わくば、その側面が意図的でないことを願っています)

&quot; foo&quot;についてファンキーなのは、は、データ型からは明らかではない暗黙的な情報の種類です(ブール部分がtrueである限り、これを呼び出し続けることができます)。これが、seqバージョンをもう少し魅力的にするものです。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top