2013-04-02 5 views
2

내 코드의 출력에 문제가 있습니다. 내 목록의 null 조건을 확인할 때가되었습니다.Lisp에서 mapcar를 사용하지 않고 목록에 숫자를 곱하면 (0120)

내가 작성하려고하는 질문은 다음과 같습니다. 숫자로 된 두 개의 간단한 목록을 입력으로 사용하는 vecmul 함수를 작성하십시오. vecmul은 벡터를 곱하기 때문에 이러한 목록을 좌표 적으로 곱해야합니다. 두리스트가 같은 길이라고 가정합니다. [예 : (vecmul '(2 3 4 5) '(1 4 5 2))(2*1 3*4 4*5 5*2) 또는 (2 12 20 10)을 반환합니다. 당신은 지금까지 제가 정확한 숫자를 얻고있다

(defun vecmul (list list2) 
    (cond ((null list) 0) 
    (t (cons (* (car list) (car list2)) 
       (vecmul (cdr list) (cdr list2)))))) 

[170]> (setq l '(2 4 6)) 
(2 4 6) 
[171]> (setq r '(1 3 5)) 
(1 3 5) 
[172]> (vecmul l r) 
(2 12 30 . 0) 

가이 기능을 위해

mapcar를 사용할 수 없습니다, 그것은 목록에 추가하고 단지이다 "." 목록의 끝에는 "0"이 표시됩니다. 나는 재귀 적 권리를 멈추지 않거나 cond를 올바르게 작동하지 않기 때문에 그것이 확실하다고 확신한다. 나는 그것을 정정하는 방법을 모를 뿐이다.

답변

4

거의 옳았습니다. 그러나 올바른 종료가 nil 일 때 0으로 목록을 종료합니다. 이 코드는 작동합니다

(defun vecmul (list list2) 
    (cond ((null list) nil) 
    (t (cons (* (car list) (car list2)) (vecmul (cdr list) (cdr list2)))))) 

당신이 (cons 1 2) 전화

는 단점은 (1 . 2)을 기록 얻을 세포. (1 2 3 4 5)(1 . (2 . (3 . (4 . (5 . nil)))))의 줄임말입니다. 마지막 cons 셀의 cdr이 이 아니고 nil이 아니라면 (1 . (2 . (3 . (4 . (5 . 6)))))이되고 (1 2 3 4 5 . 6)이됩니다.

4

Neil Forrester가 귀하의 질문에 답변했습니다.

기타 참고 사항. Lisp에서 현대 이름을 사용하십시오 : firstrest. 간단한 진실과 거짓의 결정이있는 경우

(defun vecmul (list1 list2) 
    (cond ((null list1) nil) 
     (t (cons (* (first list1) (first list2)) 
       (vecmul (rest list1) (rest list2)))))) 

, IF 더 좋을 수 있습니다. 목록 작업이 관련되어 있으므로 다음과 같이 작성하고 WHEN을 사용하지 마십시오.

(defun vecmul (list1 list2) 
    (if (null list1) 
     nil 
    (cons (* (first list1) (first list2)) 
      (vecmul (rest list1) (rest list2))))) 

최고 사용 실제 코드의 루프 구조 또는 매핑. 위와 같이 재귀에는 스택 깊이 제한이 있습니다. 루프에는 이러한 제한이 없습니다.

(defun vecmul (list1 list2) 
    (loop for e1 in list1 and e2 in list2 
     collect (* e1 e2))) 

또는

(defun vecmul (list1 list2) 
    (mapcar #'* list1 list2))