2017-03-20 9 views
3
(defun split-list (L) 
    (if (endp L) 
    '(nil nil) 
    (let ((x (split-list (cdr L)))) 
     (list (cons (car L) (cadr x))(car X)) 
     ))) 

이것은 내가 가지고있는 코드입니다. 그것은 잘 작동합니다 :스플릿리스트 용 Lisp 재귀

(split-list '(1 2 3 4 5 6)) 
((1 3 5) (2 4 6)) 

하지만 재귀 부분에 대한 설명이 필요합니다.

우리는 기능 (split-list (cdr L))를 호출 할 때 나는 그것이 23456. 및 (cadr X) 3입니다에 123,456에서 진행 확신하지만 어떻게 5가 온거야?

기능을 수행했을 때 (split-list (cdr L))x이 3456이 아니고 (cadr x)이 4가되어야합니까? 그것은 다른 반쪽과 틀리며 똑같습니다. (car x)은 3이어야하며 잘못되었습니다.

누구든지 설명해 주시겠습니까?

답변

4

나는이 같은 재귀 split-list를 다시 작성합니다 :

(defun split-list (list) 
    (if (endp list) 
     (values nil nil) 
    (multiple-value-bind (split1 split2) 
     (split-list (rest list)) 
     (values (cons (first list) split2) 
       split1)))) 

위는 여러 값을 사용합니다. 이 함수는 분할 결과를 두 개의 값으로 반환합니다. carfirstcdrrest으로 대체합니다. 더 나은 이름이지만 기능은 동일합니다. multiple-value-bind은 및 split2 변수에 대한 재귀 호출 split-list 호출의 두 값을 바인딩합니다. values 함수는 두 개의 인수를 두 개의 값으로 반환합니다. 당신은 그것의 실행을 추적 할 수

CL-USER 20 > (split-list '(a b c d e f)) 
(A C E) 
(B D F) 

:

CL-USER 21 > (trace split-list) 
(SPLIT-LIST) 

CL-USER 22 > (split-list '(a b c d e f)) 
0 SPLIT-LIST > ((A B C D E F)) 
    1 SPLIT-LIST > ((B C D E F)) 
    2 SPLIT-LIST > ((C D E F)) 
     3 SPLIT-LIST > ((D E F)) 
     4 SPLIT-LIST > ((E F)) 
      5 SPLIT-LIST > ((F)) 
      6 SPLIT-LIST > (NIL) 
      6 SPLIT-LIST < (NIL NIL) 
      5 SPLIT-LIST < ((F) NIL) 
     4 SPLIT-LIST < ((E) (F)) 
     3 SPLIT-LIST < ((D F) (E)) 
    2 SPLIT-LIST < ((C E) (D F)) 
    1 SPLIT-LIST < ((B D F) (C E)) 
0 SPLIT-LIST < ((A C E) (B D F)) 
(A C E) 
(B D F) 
+0

당신에게 선생님 감사 아래의 예에서

, 당신은 함수가 실제로 두 개의 값을 반환하는 것을 볼 수 있습니다! 나는 항상 재귀의 하반부에 문제가 생긴다. 요소를 없애고있는 전반은 쉽지만 아래쪽 절반. 조금 혼란스러워. 그래도 위대한 설명. – Ash