언제 필요한가요?
루프를 재귀로 적는 편이 자연스러울 때 꼬리 호출이 중요해집니다. 재귀 호출이 마지막 동작이라면, 리스펙스는 연속을 하나 더 쌓는 대신 지금 연속을 교체할 수 있습니다.
실행으로 확인하기
LISPEX
(let loop ((n 10000) (acc 0)) (if (= n 0) acc (loop (- n 1) (+ acc 1))))관측 결과
OUTPUT
10000예제 읽기
이름 있는 let이 loop를 만듭니다. 각 분기는 acc를 돌려주거나, 더 작아진 n과 새 acc를 들고 곧바로 loop를 다시 부릅니다. 호출 뒤에 남아 있는 덧셈이 없습니다. 그래서 1만 번을 돌아도 논리적으로는 루프 하나로 끝납니다.
이 순서로 생각하세요
- 꼬리 위치에는 마지막 본문과
if의 두 가지, 정규화된cond·case, 마지막and·or,do,call-with-values,apply가 들어갑니다. - 올바른 꼬리 동작이 말하는 것은 연속이 얼마나 자라느냐입니다. 실행 시간이 같다거나 무제한으로 실행된다는 뜻은 아닙니다.
- 꼬리 재귀 프로그램에도 자원 한도는 그대로 적용됩니다. 이 한도는 결정적이고 프로필마다 다릅니다.
빠르게 고르기
| 형태 | 꼬리 호출? | 이유 |
|---|---|---|
(if done? answer (loop next)) | 예 | 선택한 분기 결과를 그대로 반환 |
(begin (display x) (loop next)) | 예 | 호출이 마지막 폼 |
(+ x (loop next)) | 아니요 | 재귀 결과 뒤에 덧셈이 남음 |
(map loop items) | 콜백은 아니요 | map이 콜백 결과를 더 처리 |
꼬리 위치의 (apply loop args) | 예 | apply가 호출자의 꼬리 위치를 보존 |
흔한 오해
비꼬리 재귀는 선언된 자원 한도에 도달할 수 있습니다.
현재 경계
- 자원 오류가 깨끗하게 났다는 사실은 네이티브와 WASM의 임계값이 같다는 증거가 되지 않습니다.
다음으로
기저 사례와 누산기 변환은 재귀 가이드에서 익히세요. 꼬리 안전이 곧 무제한을 뜻하지 않는 이유는 결정성과 자원에서 설명합니다.