2010-07-09 2 views
8

동일한 유형의 항목 목록을 설명하는 유형 지정자를 정의하고자합니다. 그래서 (list-of integer)은 (붙박이 인) (array integer)과 비슷합니다. 다음과 같이 특정 유형으로 만들 수 있습니다.Common Lisp에서 일반적인 데이터 유형 지정자 (정수 목록과 같은)를 정의하는 방법은 무엇입니까?

(defun elements-are-integer (seq) 
    (every #'(lambda (x) (typep x 'integer)) seq)) 
(deftype list-of-integer() 
    '(and list (satisfies elements-are-integer))) 

그러나 이것은 가능한 모든 유형에 대해이 작업을 수행해야한다는 것을 의미합니다. 유형이 다른 유형을 인수로 취하도록이 코드를 어떻게 변경하고 즉시 satisfies 술어를 구성 할 수 있습니까? 문제는 satisfies에 전역 심볼이 필요하며 적절한 컨텍스트에서 조건 자 함수를 정의하는 방법을 알지 못합니다. (어쨌든 gensym이 필요합니다. 또한 솔루션은 다른 패키지 내부에서 유형을 생성 할 수 있도록 작동해야합니다.

답변

-1

나는 예를 (deftype-list-of integer)를 들어

(defmacro deftype-list-of (type) 
    (let* ((etfname (intern (concatenate 'string "ELEMENTS-ARE-" 
             (symbol-name type)))) 
     (ltname (intern (concatenate 'string "LIST-OF-" 
             (symbol-name type)))) 
     (tcdef `(defun ,etfname (seq) 
        (every (lambda (x) (typep x ',type)) seq))) 
     (ltdef `(deftype ,ltname() 
        '(and list (satisfies ,etfname))))) 
    (if (fboundp etfname) 
     ltdef 
     `(progn ,tcdef ,ltdef)))) 

이 하나에 해당 코드에 확장 ... 내가 DEFTYPE이 사용되지만이 매크로를해야 정확히 이해하기에 충분한 커먼 리스프를 모르는 고백해야 당신이 올렸습니다.

이 코드는 현재 패키지의 유형을 정의하지만 패키지 이름을 허용하도록 변경하면 사소한 문제가 발생합니다.

+0

감사합니다. 정확하게 원했던 것이 아니더라도 그것은 확실히 유용합니다. –

12

이 시도 :

(defun elements-are-of-type (seq type) 
    (every #'(lambda (x) (typep x type)) seq)) 

(deftype list-of-type (type) 
    (let ((predicate (gensym))) 
    (setf (symbol-function predicate) 
     #'(lambda (seq) (elements-are-of-type seq type))) 
    `(and list (satisfies ,predicate)))) 

(typep '(1 2 3) '(list-of-type integer)) 
; -> T 

(typep '(1 2 a) '(list-of-type integer)) 
; -> NIL 

(typep '(a b c) '(list-of-type symbol)) 
; -> T 
관련 문제