2011-05-09 5 views
3

나는 현재 Scalaz non-blocking future aka로 놀고있다. 약속 해. p 유형 I=>Booleanf와 술어이다꼬리 재귀와 스카 이즈 약속

@tailrec 
private def repeat(res: Promise[I]):Promise[I] = 
    res map p flatMap { 
    (b:Boolean) => 
     if(b) repeat(res flatMap f) else res 
    } 

이 유형 I=>Promise[I]와 동시 기능입니다 : 나는 다음과 같은 기능이 꼬리 재귀 만들기 위해 고군분투하고있다.

이 메서드는 주석없이 컴파일됩니다.

힌트가 있습니까? 감사합니다

답변

4

귀하의 방법은 전혀 재귀가 아닙니다. res은 잠재적으로 다른 스레드에서 실행되는 계산입니다. res map p flatMap f은 귀하의 방법에 관한 한 즉각적으로 약속을 되돌려줍니다. repeat에 대한 재발은 다른 프로세스에서 발생합니다.

약간 더 간결한 용어로 Promise은 연속 모나드이며, flatMap 호출은 자동으로 연속 전달 스타일로 변환됩니다.

1

호출이 코드에서 한 번만 나타나기 때문에 tail 재귀 적으로 보이지만 컬렉션에있는 각 요소에 대해 하나 이상의 재귀 호출이 있습니다. 적어도 그것은 컴파일러가 보는 것입니다. (일부 콜렉션에서 flatMap이라고 가정하면 p이 반환되지 않습니다.)

재귀를 익명 함수로 전달합니다. 아무도 그것을 얼마나 자주 실행할지 모른다.

+0

답장을 보내 주셔서 감사합니다. 하지만 차단하지 않고 해결할 수있는 방법에 대한 아이디어가 있습니까? – paradigmatic

+2

미안하지만 스 카즈에 익숙하지 않습니다. 방금 코드에서'p' 호출이 무엇인지, 실패했는지 알아 내려고했습니다. while 루프를 사용하는 코드의 절차 버전을 생각해 볼 수 있습니까? 이것이 가능하지 않으면 tco가있을 수 없습니다. – ziggystar

+1

"컬렉션에있는 각 요소에 대해 하나씩. 적어도 컴파일러에서 보는 것입니다." IMHO :'Promise'는 콜렉션이 아니며 컴파일러는 하나의 호출 만 보입니다 (꼬리 위치가 아님). 그러나 두 번째 단락은 이것이 꼬리 재귀가 아닌 이유를 설명하기에 정확하고 충분합니다. –