실행으로 확인하기
LISPEX
(let loop ((xs (list 1 2 3 4)) (sum 0)) (if (null? xs) sum (loop (cdr xs) (+ sum (car xs)))))관측 결과
OUTPUT
10패턴 따라가기
- 기저 사례를 찾습니다.
xs가 비면 답은 이미sum에 있습니다. - 남은 일을 줄입니다.
(cdr xs)가 항목을 정확히 하나 없애므로 유한한 올바른 리스트는 반드시 기저 사례에 닿습니다. - 답을 앞으로 운반합니다. 다음 누산기를
loop전에 계산해 재귀 호출 자체를 마지막 동작으로 남깁니다.
이 순서로 생각하세요
- 재귀 반환 뒤 작업을 결합하지 말고 누산기를 매개변수로 전달합니다.
- 마지막
if,begin,and·or,cond,case,do,call-with-values,apply경로에서도 꼬리 위치가 보존됩니다. - 테스트에서는 입력을 제한하고 연속 깊이와 실행 비용을 구분합니다.
직접 확인하기
입력 리스트에 5를 더하면 결과는 무엇이며 재귀 호출은 여전히 꼬리 위치일까요?
답
결과는 15입니다. 입력 데이터만 바뀌므로 loop는 여전히 선택한 분기의 마지막 동작입니다.
흔한 오해
꼬리 안전성은 무한 루프를 종료시키거나 자원 예산을 없애지 않습니다.
다음으로
비꼬리 함수를 바꿀 때는 꼬리 호출 매뉴얼을, 재귀 대신 fold를 고를 때는 고차 프로시저 레퍼런스를 보세요.