LINUX.ORG.RU

История изменений

Исправление den73, (текущая версия) :

Вот так вроде можно избавиться от фейковой записи ценой вставки двух форм в каждый файл, где возникает новый тип такого рода. Причём вторая из этих форм располагается весьма неудачно. Это изъян, жду ваших советов по исправлению.

;; def-type.asd
(defsystem :def-type
  :serial t
  :components ((:file "def-type-1")
               (:file "def-type-2")
               ))

;; eof


;; -*- coding: utf-8; system :def-type;  -*-  
;; def-type-1.lisp

(in-package :cl-user)

(defstruct str a b)

(defun foo ()
  (make-str :a 1 :b "1"))

(defun only-values-of-plist (plist)
  (let ((flag nil)
        (result nil))
    (dolist (e plist)
      (if flag (push e result))
      (setf flag (not flag)))
    (nreverse result)))

(defvar *known-parametric-types*)

(defmacro generate-funs-for-known-parametric-types ()
  (let* ((sources (only-values-of-plist *known-parametric-types*)))
    `(progn
       ,@sources)))

;; eof


;; -*- coding: utf-8; system :def-type;  -*- 
;; def-type-2.lisp

(in-package :cl-user)

;; от этой формы можно избавиться, если есть зацепка, позволяющая связать переменную
;; вокруг компиляции, например, 
;; https://bitbucket.org/budden/budden-tools/src/default/let-around-compile-file-and-load.lisp?at=default&fileviewer=file-view-default
(eval-when (:compile-toplevel)
  (setf *known-parametric-types* nil))

(deftype type-ab (type-a type-b)
  (print "Вот выполняется тело (deftype type-ab)")
  (let* ((predicate-name (intern (prin1-to-string `(type-ab ,type-a ,type-b))))
         (predicate-source
          `(defun ,predicate-name (value) 
             (and (typep (str-a value) ',type-a)
                  (typep (str-b value) ',type-b))))
         (result `(and str (satisfies ,predicate-name))))
    (setf (getf *known-parametric-types* predicate-name) predicate-source)
    (format t "Результат deftype: ~S" result)
    ;; определяем предикат во время макрорасширения
    (compile (eval predicate-source))
    result))

(defun bar () 
  (format t "Проверка типа вернула ~A~%"
          (typep (foo) '(type-ab integer string))))

;; а это форма обезпечит создание предикатов при загрузке
;; она должна располагаться перед кодом, исполняемым при 
;; загрузке, но после всех применений типов, что, естественно,
;; довольно ограничительно
(generate-funs-for-known-parametric-types)

(bar) 

;; eof


Чтобы два раза не вставать: в SBCL нашёлся почти годный defadvice, он называется sb-int:encapsulate . После небольшой доработки напильником (см. недавние коммиты к budden-tools) получилось, в общем-то, не хуже чем в Lispworks.

Исправление den73, :

Вот так вроде можно избавиться от фейковой записи ценой вставки двух форм в каждый файл, где возникает новый тип такого рода. Причём вторая из этих форм располагается весьма неудачно. Это изъян, жду ваших советов по исправлению.

;; def-type.asd
(defsystem :def-type
  :serial t
  :components ((:file "def-type-1")
               (:file "def-type-2")
               ))

;; eof


;; -*- coding: utf-8; system :def-type;  -*-  
;; def-type-1.lisp

(in-package :cl-user)

(defstruct str a b)

(defun foo ()
  (make-str :a 1 :b "1"))

(defun only-values-of-plist (plist)
  (let ((flag nil)
        (result nil))
    (dolist (e plist)
      (if flag (push e result))
      (setf flag (not flag)))
    (nreverse result)))

(defvar *known-parametric-types*)

(defmacro generate-funs-for-known-parametric-types ()
  (let* ((sources (only-values-of-plist *known-parametric-types*)))
    `(progn
       ,@sources)))

;; eof


;; -*- coding: utf-8; system :def-type;  -*- 
;; def-type-2.lisp

(in-package :cl-user)

;; от этой формы можно избавиться, если есть зацепка, позволяющая связать переменную
;; вокруг компиляции, например, 
;; https://bitbucket.org/budden/budden-tools/src/default/let-around-compile-file-and-load.lisp?at=default&fileviewer=file-view-default
(eval-when (:compile-toplevel)
  (setf *known-parametric-types* nil))

(deftype type-ab (type-a type-b)
  (print "Вот выполняется тело (deftype type-ab)")
  (let* ((predicate-name (intern (prin1-to-string `(type-ab ,type-a ,type-b))))
         (predicate-source
          `(defun ,predicate-name (value) 
             (and (typep (str-a value) ',type-a)
                  (typep (str-b value) ',type-b))))
         (result `(and str (satisfies ,predicate-name))))
    (setf (getf *known-parametric-types* predicate-name) predicate-source)
    (format t "Результат deftype: ~S" result)
    ;; определяем предикат во время макрорасширения
    (compile (eval predicate-source))
    result))

(defun bar () 
  (format t "Проверка типа вернула ~A~%"
          (typep (foo) '(type-ab integer string))))

;; а это форма обезпечит создание предикатов при загрузке
;; она должна располагаться перед кодом, исполняемым при загрузке 
(generate-funs-for-known-parametric-types)

(bar) 

;; eof


Чтобы два раза не вставать: в SBCL нашёлся почти годный defadvice, он называется sb-int:encapsulate . После небольшой доработки напильником (см. недавние коммиты к budden-tools) получилось, в общем-то, не хуже чем в Lispworks.

Исправление den73, :

Вот так вроде можно избавиться от фейковой записи ценой вставки двух форм в каждый файл, где возникает новый тип такого рода. Причём вторая из этих форм располагается весьма неудачно. Это изъян, жду ваших советов по исправлению.

;; def-type.asd
(defsystem :def-type
  :serial t
  :components ((:file "def-type-1")
               (:file "def-type-2")
               ))

;; eof


;; -*- coding: utf-8; system :def-type;  -*-  
;; def-type-1.lisp

(in-package :cl-user)

(defstruct str a b)

(defun foo ()
  (make-str :a 1 :b "1"))

(defun only-values-of-plist (plist)
  (let ((flag nil)
        (result nil))
    (dolist (e plist)
      (if flag (push e result))
      (setf flag (not flag)))
    (nreverse result)))

(defvar *known-parametric-types*)

(defmacro generate-funs-for-known-parametric-types ()
  (let* ((sources (only-values-of-plist *known-parametric-types*)))
    `(progn
       ,@sources)))

;; eof


;; -*- coding: utf-8; system :def-type;  -*- 
;; def-type-2.lisp

(in-package :cl-user)

;; от этой формы можно избавиться, если есть зацепка, позволяющая связать переменную
;; вокруг компиляции, например, 
;; https://bitbucket.org/budden/budden-tools/src/default/let-around-compile-file-and-load.lisp?at=default&fileviewer=file-view-default
(eval-when (:compile-toplevel)
  (setf *known-parametric-types* nil))

(deftype type-ab (type-a type-b)
  (print "Вот выполняется тело (deftype type-ab)")
  (let* ((predicate-name (intern (prin1-to-string `(type-ab ,type-a ,type-b))))
         (predicate-source
          `(defun ,predicate-name (value) 
             (and (typep (str-a value) ',type-a)
                  (typep (str-b value) ',type-b))))
         (result `(and str (satisfies ,predicate-name))))
    (setf (getf *known-parametric-types* predicate-name) predicate-source)
    (format t "Результат deftype: ~S" result)
    ;; определяем предикат во время макрорасширения
    (compile (eval predicate-source))
    result))

(defun bar () 
  (format t "Проверка типа вернула ~A~%"
          (typep (foo) '(type-ab integer string))))

(bar) 

;; а это форма обезпечит создание предикатов при загрузке
;; она должна располагаться перед кодом, исполняемым при загрузке 
(generate-funs-for-known-parametric-types)

(bar) 

;; eof


Чтобы два раза не вставать: в SBCL нашёлся почти годный defadvice, он называется sb-int:encapsulate . После небольшой доработки напильником (см. недавние коммиты к budden-tools) получилось, в общем-то, не хуже чем в Lispworks.

Исправление den73, :

Вот так вроде можно избавиться от фейковой записи ценой вставки двух форм в каждый файл, где возникает новый тип такого рода, от вставки форм можно избавиться ценой декорирования функции compile, к-рое тоже вполне осуществимо.

;; def-type.asd
(defsystem :def-type
  :serial t
  :components ((:file "def-type-1")
               (:file "def-type-2")
               ))

;; eof


;; -*- coding: utf-8; system :def-type;  -*-  
;; def-type-1.lisp

(in-package :cl-user)

(defstruct str a b)

(defun foo ()
  (make-str :a 1 :b "1"))

(defun only-values-of-plist (plist)
  (let ((flag nil)
        (result nil))
    (dolist (e plist)
      (if flag (push e result))
      (setf flag (not flag)))
    (nreverse result)))

(defvar *known-parametric-types*)

(defmacro generate-funs-for-known-parametric-types ()
  (let* ((sources (only-values-of-plist *known-parametric-types*)))
    `(progn
       ,@sources)))

;; eof


;; -*- coding: utf-8; system :def-type;  -*- 
;; def-type-2.lisp

(in-package :cl-user)

;; от этой формы можно избавиться, если есть зацепка, позволяющая связать переменную
;; вокруг компиляции, например, 
;; https://bitbucket.org/budden/budden-tools/src/default/let-around-compile-file-and-load.lisp?at=default&fileviewer=file-view-default
(eval-when (:compile-toplevel)
  (setf *known-parametric-types* nil))

(deftype type-ab (type-a type-b)
  (print "Вот выполняется тело (deftype type-ab)")
  (let* ((predicate-name (intern (prin1-to-string `(type-ab ,type-a ,type-b))))
         (predicate-source
          `(defun ,predicate-name (value) 
             (and (typep (str-a value) ',type-a)
                  (typep (str-b value) ',type-b))))
         (result `(and str (satisfies ,predicate-name))))
    (setf (getf *known-parametric-types* predicate-name) predicate-source)
    (format t "Результат deftype: ~S" result)
    ;; определяем предикат во время макрорасширения
    (compile (eval predicate-source))
    result))

(defun bar () 
  (format t "Проверка типа вернула ~A~%"
          (typep (foo) '(type-ab integer string))))

(bar) 

;; а это форма обезпечит создание предикатов при загрузке
;; она должна располагаться перед кодом, исполняемым при загрузке 
(generate-funs-for-known-parametric-types)

(bar) 

;; eof


Чтобы два раза не вставать: в SBCL нашёлся почти годный defadvice, он называется sb-int:encapsulate . После небольшой доработки напильником (см. недавние коммиты к budden-tools) получилось, в общем-то, не хуже чем в Lispworks.

Исправление den73, :

Вот так вроде можно избавиться от фейковой записи ценой вставки двух форм в каждый файл, где возникает новый тип такого рода, от вставки форм можно избавиться ценой декорирования функции compile, к-рое тоже вполне осуществимо.

;; def-type.asd
(defsystem :def-type
  :serial t
  :components ((:file "def-type-1")
               (:file "def-type-2")
               ))

;; eof


;; -*- coding: utf-8; system :def-type;  -*-  
;; def-type-1.lisp

(in-package :cl-user)

(defstruct str a b)

(defun foo ()
  (make-str :a 1 :b "1"))

(defun only-values-of-plist (plist)
  (let ((flag nil)
        (result nil))
    (dolist (e plist)
      (if flag (push e result))
      (setf flag (not flag)))
    (nreverse result)))

(defvar *known-parametric-types*)

(defmacro generate-funs-for-known-parametric-types ()
  (let* ((sources (only-values-of-plist *known-parametric-types*)))
    `(progn
       ,@sources)))

;; eof


;; -*- coding: utf-8; system :def-type;  -*- 
;; def-type-2.lisp

(in-package :cl-user)

;; от этой формы можно избавиться, если есть зацепка, позволяющая связать переменную
;; вокруг компиляции, например, 
;; https://bitbucket.org/budden/budden-tools/src/default/let-around-compile-file-and-load.lisp?at=default&fileviewer=file-view-default
(eval-when (:compile-toplevel)
  (setf *known-parametric-types* nil))

(deftype type-ab (type-a type-b)
  (print "Вот выполняется тело (deftype type-ab)")
  (let* ((predicate-name (intern (prin1-to-string `(type-ab ,type-a ,type-b))))
         (predicate-source
          `(defun ,predicate-name (value) 
             (and (typep (str-a value) ',type-a)
                  (typep (str-b value) ',type-b))))
         (result `(and str (satisfies ,predicate-name))))
    (setf (getf *known-parametric-types* predicate-name) predicate-source)
    (format t "Результат deftype: ~S" result)
    ;; определяем предикат во время макрорасширения
    (compile (eval predicate-source))
    result))

(defun bar () 
  (format t "Проверка типа вернула ~A~%"
          (typep (foo) '(type-ab integer string))))

(bar) 

;; а это форма обезпечит создание предикатов при загрузке
;; Опять же, если есть декоратор для процесса компиляции, то это можно убрать из файла
(generate-funs-for-known-parametric-types)

;; eof


Чтобы два раза не вставать: в SBCL нашёлся почти годный defadvice, он называется sb-int:encapsulate . После небольшой доработки напильником (см. недавние коммиты к budden-tools) получилось, в общем-то, не хуже чем в Lispworks.

Исходная версия den73, :

Вот так вроде можно избавиться от фейковой записи ценой вставки двух форм или ценой декорирования функции compile.

;; def-type.asd
(defsystem :def-type
  :serial t
  :components ((:file "def-type-1")
               (:file "def-type-2")
               ))

;; eof


;; -*- coding: utf-8; system :def-type;  -*-  
;; def-type-1.lisp

(in-package :cl-user)

(defstruct str a b)

(defun foo ()
  (make-str :a 1 :b "1"))

(defun only-values-of-plist (plist)
  (let ((flag nil)
        (result nil))
    (dolist (e plist)
      (if flag (push e result))
      (setf flag (not flag)))
    (nreverse result)))

(defvar *known-parametric-types*)

(defmacro generate-funs-for-known-parametric-types ()
  (let* ((sources (only-values-of-plist *known-parametric-types*)))
    `(progn
       ,@sources)))

;; eof


;; -*- coding: utf-8; system :def-type;  -*- 
;; def-type-2.lisp

(in-package :cl-user)

;; от этой формы можно избавиться, если есть зацепка, позволяющая связать переменную
;; вокруг компиляции, например, 
;; https://bitbucket.org/budden/budden-tools/src/default/let-around-compile-file-and-load.lisp?at=default&fileviewer=file-view-default
(eval-when (:compile-toplevel)
  (setf *known-parametric-types* nil))

(deftype type-ab (type-a type-b)
  (print "Вот выполняется тело (deftype type-ab)")
  (let* ((predicate-name (intern (prin1-to-string `(type-ab ,type-a ,type-b))))
         (predicate-source
          `(defun ,predicate-name (value) 
             (and (typep (str-a value) ',type-a)
                  (typep (str-b value) ',type-b))))
         (result `(and str (satisfies ,predicate-name))))
    (setf (getf *known-parametric-types* predicate-name) predicate-source)
    (format t "Результат deftype: ~S" result)
    ;; определяем предикат во время макрорасширения
    (compile (eval predicate-source))
    result))

(defun bar () 
  (format t "Проверка типа вернула ~A~%"
          (typep (foo) '(type-ab integer string))))

(bar) 

;; а это форма обезпечит создание предикатов при загрузке
;; Опять же, если есть декоратор для процесса компиляции, то это можно убрать из файла
(generate-funs-for-known-parametric-types)

;; eof


Чтобы два раза не вставать: в SBCL нашёлся почти годный defadvice, он называется sb-int:encapsulate . После небольшой доработки напильником (см. недавние коммиты к budden-tools) получилось, в общем-то, не хуже чем в Lispworks.