2010-07-09 8 views
8

Chciałbym zdefiniować specyfikator typu, który opisuje listę rzeczy tego samego typu. Więc chciałbym mieć (list-of integer) podobny do (array integer) (który jest wbudowany). Jestem w stanie stworzyć go dla konkretnego typu, tak:W Common Lisp, jak zdefiniować rodzajowy specyfikator typu danych (jak lista liczb całkowitych)?

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

Oznacza to jednak, muszę to zrobić dla każdego możliwego typu. Jak mogę zmienić ten kod tak, aby typ przyjmował inny typ jako argument i konstruować predykat satisfies w locie? Problem polega na tym, że satisfies wymaga globalnego symbolu i nie wiem, jak zdefiniować funkcję predykatu we właściwym kontekście (domyślam się, że muszę jakoś to zrobić, ale jak?). Rozwiązanie powinno również działać, aby typ mógł zostać utworzony w innym pakiecie.

Odpowiedz

-1

Muszę przyznać, że nie wiem, Common Lisp wystarczająco dokładnie zrozumieć, co deftype stosuje, ale to makro powinno wystarczyć ...

(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)))) 

Na przykład (deftype-list-of integer) rozszerza kodować odpowiednikiem jednego wysłałeś.

Ten kod definiuje typ w bieżącym pakiecie (przypuszczam), ale zmiana go w celu umożliwienia przyjęcia nazwy pakietu powinna być banalna.

+0

Dzięki. Jest to zdecydowanie przydatne, mimo że nie jest to dokładnie to, czego chciałem. –

12

Spróbuj tego:

(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 
Powiązane problemy