문제

다음과 같이 주어진다 :

#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"에 대해 너무 펑키 한 것은 데이터 유형에서 분명하지 않은 일종의 암시 적 정보라고 생각합니다 (부리 부분이 사실 인 한 계속 해서이 문제를 계속 호출 할 수 있습니다). 더욱 매력적인.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top