2012-01-21 3 views
6

저는 새 언어로 Lisp을 선택하려고합니다. 함수의 일부가 전달 된 목록의 각 요소에서 작동하도록하는 방법에 대해 몇 가지 문제를 겪고 있습니다. 이 문제를 가져 오는 방법을 학습의 목적 defun을 인수로 사용하여 목록을

, 나는리스트의 요소 중 하나가 0 인 경우 까악 까악하지 않는 부문의 상당히 기본적인 양식을 작성하려고 (하지만 대신 0 반환)

(defun divtest (elements) 
    (dolist (x elements) 
    (if (zerop x) 0()) 
    (/ elements))))) 
을하고있다 산출 어느

(divtest '(20 2 5)) 

:로

나는 이것을 실행하려고

*** - /: (20 2 5) is not a number 

실패 지점은 함수에 전달하기 전에 목록의 요소를 "추출하지"않는다는 사실에 뿌리를 둔 것처럼 보입니다.이 경우 x는 0으로 평가되지 않으므로 의도 한대로 작동하지 않습니다. 내가 맞다면 누군가이 "추출"을 수행하는 방법을 말해 줄 수 있습니까?


참고 :이 질문은 one that I've asked earlier 관련,하지만이 특정 문제를 의도 한대로 이전 대답의 일부가 실제로 작동 할 수있는 대한 불분명 해요으로 나는 기초에 더 가기로 결정한다

답변

5

/은 하나 이상의 숫자를 인수로 취하지 만 코드에서는 목록을 전달하는 중입니다. 분명히 작동하지 않습니다. 함수 apply은 여기에 친구입니다. (apply #'foo a b (list c d e))(foo a b c d e)과 같습니다. 사용할 함수와 최종 목록 사이의 apply에 대한 인수는 선택 사항이므로 (apply #'/ '(20 2 5))(/ 20 2 5)과 같습니다.

또한 0을 제거하려는 시도가 작동하지 않습니다. dolist은 인수 목록 elements의 각 항목에 대해 본문을 평가하지만 실제로는 elements의 내용을 변경하지 않습니다. dolist 평가 본 결과는 예상 한대로 소스 요소에 다시 할당되지 않습니다.

함수 remove-if (및 그 상응하는 대응 물, delete-if)이 당신이 찾고있는 것입니다. 다음은 그것을 사용하는 방법을 보여줍니다 (많은 옵션 인수를 필요로하는데,이 목적을 위해 걱정할 필요가 없습니다).

(defun divtest (elements) 
    (apply #'/ (remove-if #'zerop elements))) 

는 또한 elements 목록 (I 함수의이해야 할 무엇을 의미하는지 이해 가정)의 첫 번째 요소로 제로가있는 경우이 제대로 작동하지 않습니다. 그래서 대신 같은 것을 원할 수도 있습니다

(defun divtest (elements) 
    (apply #'/ (first elements) (remove-if #'zerop (rest elements)))) 

자세한 내용은 하이퍼 스페셜을 참조하십시오.

+2

APPLY 대신 REDUCE 사용 –

+0

그냥 궁금 해서요 : 그 유틸리티는 무엇이겠습니까? – Hugh

+0

이렇게하면 CALL-ARGUMENT-LIMIT (표준 CL 상수) 최대 길이뿐만 아니라 임의의 긴 목록을 처리 할 수 ​​있습니다. Common Lisp에는 구현에 따라 최대 인수 개수가 있습니다. 이 번호는 50 이상이어야합니다. 즉, 구현은 50 개의 인수 (또는 그 이상) 만 지원하면됩니다. 따라서 위의 함수는 숫자 목록이 함수 /를 호출하는 인수의 수보다 길 때 일부 구현에서는 실패 할 수 있습니다. –

0

(/ elements) 대신 (apply/elements)을 시도하십시오. 나는 Lisp의 대부분의 방언에서 작동해야한다고 생각한다.

+0

처럼 쓸 수'/'당신'/'의 데이터 셀에 함수를 지정하지 않은 경우. – Hugh

1

아니면 당신은 인용해야이

(defun divtest (elements) 
    (if (member 0 elements) 
     0 
     (apply #'/ elements))) 
1
(block exit 
    (reduce #'/ '(1 2 3 0 5) 
      :key (lambda (x) 
       (if (zerop x) 
        (return-from exit 0) 
        x)))) 
관련 문제