2010-12-26 4 views
11

값 목록이 주어지면 모든 요소가 NIL이 아니면 T로, NIL이 아닌 경우 NIL로 줄이기를 원합니다. 이처럼Common Lisp에서 불리언 값 목록을 어떻게 줄일 수 있습니까?

(apply #'and (get-some-list)) 

: 이것은 나에게 오류를 제공

[11]> (defun my-and (x y) (and x y)) 
MY-AND 

[12]> (reduce #'my-and '(T T T T T)) 
T 

[13]> (reduce #'my-and '(T T T T NIL)) 
NIL 

왜 '#'와 '잘못되었습니다

(reduce #'and (get-some-list)) 

이것은 내가 가지고 올 것 중에 최고입니다 ? Common Lisp에서 이것을하는 관용적 인 방법이 있습니까?

답변

8

#'andand이 매크로가 아니기 때문에 잘못되었습니다.

당신은 람다를 사용하여 명명 된 함수를 정의 할 필요가 주위 얻을 수 있습니다 : #' 등의 지름길 그래도 없다

(reduce (lambda (x y) (and x y)) (get-some-list) :initial-value t) 

.

또는 식별 기능과 함께 every을 술어로 사용할 수도 있습니다.

+1

'reduce'의 첫 번째 인수가 0 또는 2 개의 인수로 호출 될 수 있으므로 예제는 ** wrong **입니다 (CL hyperspec 참조). 또한 '초기 값'을 제공하지 않습니다. 빈리스트 나 길이가 1 인리스트를 줄이기를 원한다면 예제는 작동하지 않습니다. 올바른 버전은 예를 들어'(lambda (& optional (x T) (y T) (xy))' . –

3

'sharp-quote'기호는 일반적인 기능에서만 사용할 수 있습니다.

(every #'identity '(T T T T T)) -> T 

(every #'identity '(T T T T NIL)) -> NIL 

이 아마 가장 효율적인 방법은 LOOP 사용 :

Note that only ordinary functions can be quoted with #’. It is an error to 
quote a macro function or special function this way, or to quote a symbol with 
#’ if that symbol does not name a function. 

> #’if 
Error: IF is not an ordinary function. 

COMMON LISP: A Gentle Introduction to Symbolic Computation, page 202

19

당신은 모든 함수를 사용할 수 있습니다

(loop for element in '(T T T T nil) always element) -> NIL 

장점은 목록 요소를 통한 함수 호출이 필요 없다는 것입니다.

#'은 표현을 읽는 동안 FUNCTION으로 확장되는 읽기 매크로입니다. 따라서 #'and은 (함수 AND)입니다.

FUNCTION 여기에 설명된다 : http://www.lispworks.com/documentation/HyperSpec/Body/s_fn.htm

FUNCTION 함수 이름 또는 람다 식을 취하여 해당 기능 오브젝트를 반환한다.

과 여기에 정의됩니다 : http://www.lispworks.com/documentation/HyperSpec/Body/m_and.htm

는 것을 말한다 및 매크로가 아닌 기능입니다. 결과적으로 FUNCTION은 해당 함수 오브젝트를 리턴하는 매크로가 아닌 함수가 필요하기 때문에 (FUNCTION AND)는 작동하지 않습니다. sepp2k가 그의 대답에서 설명했듯이, LAMBDA를 사용하여 함수를 생성하고 그 함수 내에서 매크로 AND를 사용할 수 있습니다. 매크로는 값으로 전달할 수 없으며 나중에 FUNCALL 또는 APPLY를 통해 호출 할 수 있습니다. 이 기능은 기능에서만 작동합니다.

이 용액

(reduce (lambda (x y) (and x y)) (get-some-list)) 

로 작성된 람다 (function (lambda (...) ...))(lambda (...) ...)로 확장 매크로이다.

그래서 위의 정말 : CL의 값과 기능에 대한 네임 스페이스 사이에 차이가 있기 때문에

(reduce #'(lambda (x y) (and x y)) (get-some-list)) 

기능이 필요할 같이 쓸 수있다

(reduce (function (lambda (x y) (and x y))) (get-some-list)) 

. REDUCE는 값으로 인수로 전달 된 함수를 가져와야합니다. 그래서 우리는 FUNCTION의 목적 인 함수 네임 스페이스에서 함수를 가져와야합니다. 함수 객체를 전달하고자 할 때마다 함수 네임 스페이스에서 함수 객체를 가져와야합니다. 로컬 함수의 경우, 예를 들어

:로 확장 간이 매크로로

(flet ((my-and (x y) (and x y))) 
    #'my-and) 

LAMBDA (FUNCTION (람다 ...)) CL의 설계 단계에서 첨가되었다.

관련 문제