Bir validator yuvası ile standart yuvaları geliştiren bir meta sınıfı tanımladığımda, :validator (clavier:valid-email "The email is invalid")
ifadesini, ifadenin sonucunu kaydetmek yerine funcallable, ifadenin kendisini depolar. Standart yuvaları genişletirken bir adımı kaçırıyor muyum? İfadenin depolanmadan önce değerlendirildiğinden nasıl emin olurum? SBCL 1.2.11 btw kullanıyorum. Bir funcallable değildir: Burada söz (GEÇERLİ-EMAIL "e-posta geçersiz" clavier) olarak bir örneğini verirken kod başarısızÖzel yuva seçenekleri bağımsız değişkenine herhangi bir azaltma uygulamıyor
(unless (find-package 'clavier)
(ql:quickload :clavier))
(unless (find-package 'c2mop)
(ql:quickload :c2mop))
(defpackage #:clos2web/validation
(:use #:cl)
(:import-from #:c2mop
#:standard-class
#:standard-direct-slot-definition
#:standard-effective-slot-definition
#:validate-superclass
#:direct-slot-definition-class
#:effective-slot-definition-class
#:compute-effective-slot-definition
#:slot-value-using-class))
(in-package #:clos2web/validation)
(defun true (value)
"Always return true."
(declare (ignore value))
t)
(defclass validation-class (standard-class)
()
(:documentation "Meta-class for objects whose slots know how to validate
their values."))
(defmethod validate-superclass
((class validation-class) (super standard-class))
t)
(defmethod validate-superclass
((class standard-class) (super validation-class))
t)
(defclass validation-slot (c2mop:standard-slot-definition)
((validator :initarg :validator :accessor validator :initform #'true
:documentation "The function to determine if the value is
valid. It takes as a parameter the value.")))
(defclass validation-direct-slot (validation-slot
standard-direct-slot-definition)
())
(defclass validation-effective-slot (validation-slot
standard-effective-slot-definition)
())
(defmethod direct-slot-definition-class ((class validation-class) &rest initargs)
(declare (ignore initargs))
(find-class 'validation-direct-slot))
(defmethod effective-slot-definition-class ((class validation-class) &rest initargs)
(declare (ignore initargs))
(find-class 'validation-effective-slot))
(defmethod compute-effective-slot-definition
((class validation-class) slot-name direct-slot-definitions)
(let ((effective-slot-definition (call-next-method)))
(setf (validator effective-slot-definition)
(some #'validator direct-slot-definitions))
effective-slot-definition))
(defmethod (setf slot-value-using-class) :before
(new (class validation-class) object (slot validation-effective-slot))
(when (slot-boundp slot 'validator)
(multiple-value-bind (validp msg)
(funcall (validator slot) new)
(unless validp
(error msg)))))
;; Example usage
(defclass user()
((name :initarg :name)
(email :initarg :email :validator (clavier:valid-email "The email is invalid") :accessor email))
(:metaclass validation-class))
(let ((pepe (make-instance 'user :name "Pepe" :email "[email protected]")))
(setf (email pepe) "FU!")) ;; should throw
yılında kodudur.
(CLAVIER:VALID-EMAIL
"The email is invalid") fell through ETYPECASE expression.
Wanted one of (FUNCTION SYMBOL).
[Condition of type SB-KERNEL:CASE-FAILURE]
'Defclass' bir şeyleri değerlendirmez, bu nedenle form yuva seçeneği olarak saklanır. En iyi çözümü düşünüyorum. Sbcl'de – Svante
, canonicalize-defclass-yuvaları yuvaların işlenmesiyle ilgilenir ve tanımın enverine erişir, çevreyi kullanarak standart olmayan seçenekleri azaltmak için nasıl uygun hale getirilebileceğine dair herhangi bir işaretçiniz var mı? – PuercoPop