Jon이 이미 말했듯이 함수는 꼬리 재귀가 아닙니다. 기본 문제는 번을 번으로 재귀 적으로 호출해야한다는 것입니다 (에 전달 된 λ 함수에서 수행 된 xs
목록의 모든 요소에 대해 한 번).
실제로 여러 번의 재귀 호출을 수행해야하는 경우 연속 전달 스타일 또는 즉 필수 스택을 사용하는 것이 유일한 옵션 일 수 있습니다.연속체 뒤에있는 아이디어는 모든 함수가 결과가 사용 가능할 때 실행되어야하는 또 다른 함수 (마지막 인수로)를 취한다는 것입니다.
다음의 예 (오른쪽) 기반 정상 (왼쪽) 버전과 계속
let res = foo a b fooCont a b (fun res ->
printfn "Result: %d" res printfn "Result: %d" res)
연속 통과 스타일의 함수를 작성하는 방법을 보여줍니다, 당신은 계속 기반 사용해야합니다 fold
기능도 있습니다.
List.fold g acc (List.map (fun xxs -> myfunc f xxs) xs)
가되다 : 먼저 fold
의 람다 함수에 map
에서 수행 작업을 이동하여 map
를 사용하여 피할 수는 다음과 같이
List.fold (fun state xxs -> g state (myfunc f xxs)) acc xs
그런 다음 코드를 다시 작성할 수 있습니다 (참고 모두 f
및 g
은 질문에 표시되지 않았지만 이제는 연속 기반 함수이므로 계속을 나타내는 추가 인수가 사용됩니다.
,210
List.foldCont
기능은 fold
의 연속 기반 버전이며, 다음과 같이 쓸 수있다 : 당신이 완전한 작업 예제를 게시하지 않았기 때문에
module List =
let rec foldCont f (state:'TState) (list:'T list) cont =
match list with
| [] -> cont state
| x::xs -> foldCont f state xs (fun state ->
f x state cont)
, 내가 정말 코드를 테스트 할 수 있지만 내 생각 작동해야합니다.
답변에'mapCont' 또는 단점이 필요하지 않습니까? –
연속성 전달 스타일에 대한 배경 지식을 읽으면서 마침내 내 코드에서 변경을 구현할 수있었습니다. 그러나, 나는 또한 본문에서 재귀 함수를 여러 번 호출하지 않기 위해 위 코드에서 정말로 내린 코드를 변경할 수 있음을 발견했습니다. 그러나 여기에 제공된 대답이 실제로 도움이되었습니다. 이 스타일에 익숙해 져야합니다. – vis