문제
다음과 같이 주어진다 :
#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"를 시퀀스 표현식으로 변환하기 위해 번거 로움을 통과해야합니까?
해결책
이것은 하나의 해결책이지만 개인적으로 그것이 건설의 남용이라고 생각합니다.
#light
while
(let (c,x) = foo()
if c then print_any !x
c)
do ()
다른 팁
내 의견으로는 약간 더 나은 또 다른 해결책. 조건 조항 범위에서 x를 가져 와서 더 높은 범위에서 사용할 수있는 참조 Y에 넣습니다. 여전히 최고의 (기능적) 솔루션은 아니지만 작동합니다.
let y = ref 1
while (let (c,x) = foo()
y := !x
c)
do printf "%i" !y
나는 당신을 생각합니다 rec loop
솔루션은 가장 기능적인 것이기 때문에 가장 잘 작동합니다 (FOO는 상태를 사용하더라도 부작용을 피함) 및 가장 일반적인 것 (FOO와 동시에 모든 기능에서 작동 함)입니다. 타이핑이 길지만 FOO와 같은 더 많은 기능을 사용하면 루프가 FOO를위한 단일 가장 짧은 솔루션보다 생산적입니다.
나는 심지어 약간의 루프를 더 일반화하고 당신이 '진정한'상황에서 가치로하고 싶은 행동을 추상화 할 것입니다.
let loop f a =
let rec loop2() =
match f() with
| (true, x) ->
a x
loop2()
| (false, _) -> ()
loop2()
loop foo print_any
FOO가 고정되어 있다고 가정 할 때 "foo"를 소비하는 방법에 대한 다른 제안을 좋아합니다.
코에 "foo"코드가 냄새가납니다. "foo"를 라인을 따라 "바"로 변환하는 것이 합리적이라면
let bar =
let x = ref 10
seq {
x := !x - 1
while !x <> 0 do
yield x
x := !x - 1
}
bar |> Seq.iter print_any
그런 다음 나는 그것을 할 것입니다. 그러나 "바"는 다소 더 좋지만 여전히 비린내처럼 보입니다. ( "Bar"에서, 나는 "foo"가했던 것처럼 "int"가 아닌 "int ref"를 반환하는 이상한 측면을 보존했지만, 그 측면이 의도하지 않은가?)
"foo"에 대해 너무 펑키 한 것은 데이터 유형에서 분명하지 않은 일종의 암시 적 정보라고 생각합니다 (부리 부분이 사실 인 한 계속 해서이 문제를 계속 호출 할 수 있습니다). 더욱 매력적인.