2010-07-09 6 views
8

Je voudrais définir un spécificateur de type qui décrit une liste de choses du même type. Donc, je voudrais avoir (list-of integer) similaire à (array integer) (qui est intégré). Je suis en mesure de créer pour un type spécifique, comme celui-ci:En Common Lisp, comment définir un spécificateur de type de données générique (comme une liste d'entiers)?

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

Cependant, cela signifie que je dois le faire pour tous les types possibles. Comment puis-je changer ce code pour que le type prenne un autre type en argument, et construire le prédicat satisfies à la volée? Le problème est que le satisfies nécessite un symbole global, et je ne sais pas comment définir la fonction de prédicat dans le contexte approprié (je suppose que j'ai besoin de gensym en quelque sorte, mais comment?). De plus, la solution devrait fonctionner pour que le type puisse être créé dans un autre paquet.

Répondre

-1

Je dois avouer que je ne connais pas assez Lisp commun pour comprendre exactement ce que DEFTYPE est utilisé pour, mais cette macro devrait le faire ...

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

Par exemple (deftype-list-of integer) étend au code équivalent à celui vous avez posté.

Ce code définit le type dans le paquet courant (je suppose), mais le changer pour autoriser l'acceptation d'un nom de paquet devrait être trivial.

+0

Merci. C'est certainement utile, même si ce n'est pas ce que je voulais exactement. –

12

Essayez ceci:

(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 
Questions connexes