質問
次の場合:
#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バージョンをもう少し魅力的にするものです。