제가 이해한 게 맞는지 봐 주실 수 있을까요? 연습 삼아 짠 continuation-passing 방식 합계예요.
let rec sumK (xs: int list) (k: int -> int) =
match xs with
| [] -> k 0
| x :: rest -> sumK rest (fun s -> k (s + x))
let xs = List.replicate 1_000_000 1
printfn "%d" (sumK xs id)
dotnet run -c Release는 1000000을 출력해요. 그냥 dotnet run, 즉 Debug는 스택 오버플로로 죽어요. 같은 소스, 같은 기기예요. 안의 호출이 전부 꼬리 위치라서 꼬리 호출 문제 같은데, 빌드의 어느 부분이 그걸 정하는지는 모르겠어요. Debug에서 뭔가를 켜는 게 정직한 해결일 수도 있고, 코드가 거기에 기대지 않게 고쳐야 할 수도 있어요.
영어에서 번역·원문 보기Could someone check my reading of this? A continuation-passing sum, written as an exercise.
let rec sumK (xs: int list) (k: int -> int) =
match xs with
| [] -> k 0
| x :: rest -> sumK rest (fun s -> k (s + x))
let xs = List.replicate 1_000_000 1
printfn "%d" (sumK xs id)
dotnet run -c Release prints 1000000. A plain dotnet run, which is Debug, dies with a stack overflow. Same source, same machine. I suspect tail calls, since every call in there is in tail position, but I don't know which part of the build decides it. Maybe the honest fix is to turn something on for Debug, or maybe the code should stop relying on it.