В языке Common LISP, как определить универсальный спецификатор типа данных (как список целых чисел)?

Я хотел бы определить спецификатор типа, который описывает список вещей того же типа. Таким образом, я хотел бы иметь (list-of integer) подобный (array integer) (который встроен). Я могу создать его для определенного типа, как это:

(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 это так или иначе, но как?). Кроме того, решение должно работать так, чтобы тип мог быть создан в другом пакете.

9
задан J S 8 July 2010 в 19:00
поделиться

1 ответ

Должен признаться, я не настолько хорошо знаю common lisp, чтобы понять, для чего именно используется deftype, но этот макрос должен это сделать...

(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-list-of integer) расширяется до кода, эквивалентного тому, который вы разместили.

Этот код определяет тип в текущем пакете (я полагаю), но изменение его для возможности принимать имя пакета должно быть тривиальным.

-1
ответ дан 2 November 2019 в 23:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: