Scheme / Racket에서 꼬리 재귀를 사용하여 추가 절차를 구현하는 방법은 무엇입니까? [복제]
Nov 14 2020
오랫동안 나는 꼬리 재귀 (반복)를 사용하여 Racket에서 추가 절차를 구현하려고 노력하고 있습니다.
지금까지 내가 한 최고의 솔루션은 다음과 같습니다.
(define (my-reverse lst)
(define (iter lst reversed)
(if (null? lst)
reversed
(iter (cdr lst) (cons (car lst) reversed))))
(iter lst '()))
(define (append-iter el lst)
(my-reverse (cons el (my-reverse lst))))
(append-iter 4 '(1 2 3)) ; (1 2 3 4)
내 질문은 더 나은 구현 방법이 있는지 여부입니다.
답변
4 ÓscarLópez Nov 14 2020 at 15:01
글쎄, 그것은 "better"에 대한 당신의 정의에 달려 있습니다. :). 솔루션은 간단하며 꼬리 재귀를 사용하여 목록 끝에 요소를 추가하는 자체 프로 시저를 작성하는 더 간단한 방법을 찾을 수 없습니다.
내 유일한 코멘트는 my-reverse
내장 reverse
프로 시저 와 동일한 작업을 수행 한다는 것입니다. 가장 확실하게 꼬리 재귀 적이므로 다음과 같이 간단히 작성할 수 있습니다.
(define (append-iter el lst)
(reverse (cons el (reverse lst))))
연속 전달 스타일 을 사용하는 것이 괜찮다 면 다음 솔루션도 꼬리 재귀 적이며 가장 기본적인 기본 절차에만 의존합니다.
(define (append-iter el lst)
(append-cps lst (cons el '()) (lambda (x) x)))
(define (append-cps lst1 lst2 k)
(if (null? lst1)
(k lst2)
(append-cps
(cdr lst1)
lst2
(lambda (appended-cdr)
(k (cons (car lst1) appended-cdr))))))
어느 쪽이든 예상대로 작동합니다.
(append-iter 4 '(1 2 3))
=> '(1 2 3 4)
궁금한 점이 있다면 CPS 솔루션이 아래 표시된 것과 같은 식으로 평가되어 자연스럽게 답을 얻을 수 있습니다.
((lambda (append-cdr)
((lambda (appended-cdr)
((lambda (appended-cdr)
((lambda (x) x)
(cons 1 appended-cdr)))
(cons 2 appended-cdr)))
(cons 3 append-cdr)))
'(4))
=> '(1 2 3 4)
1 WillNess Nov 14 2020 at 16:51
예,
(define (rev-append lst reversed)
(if (null? lst)
reversed
(rev-append (cdr lst)
(cons (car lst) reversed))))
(define (append-iter el lst)
(rev-append (rev-append lst '())
(cons el '())))
약간 "더 좋음"입니다.
rev-append
귀하 my-reverse
의 것 iter
입니다. 자체 최고 수준의 바인딩이 필요합니다.