EmilySeville7cfg · 2022-12-20 11:37
Let's say I have the following structure:
(cl-defstruct person (name :type string) (age :type integer))
How to make name not to be empty string and age be always positive and less than 200 value for instance? I am looking for smth like getter/setter functionality. Is it right that I have to just implement my own functions named like `person-set-age` with such checks?
ieure · 2022-12-20 17:50
What you're asking to do is validation, which goes beyond what most type systems can express.
If you want to do this, the best approach is:
Use EIEIO / `defclass` instead of structs.
Make a class to do the validation, which stores slot names and predicates in its own slot, ex:
(defclass object-validator ()
((slot-predicates
:documentation "Alist of (SLOT-NAME . PREDICATE-FUNCTION) used to validate objects.")))
(defmethod validate-slot-value ((ov object-validator) slot-name value)
(when-let ((pred (cdr (assoc slot-name (slot-value ov 'slot-predicates)))))
(unless (funcall pred value)
(error "Invalid slot: %s" slot-name))))
(defmethod validate-slot ((ov object-validator) slot-name)
(when (slot-boundp ov slot-name)
(validate-slot-value ov slot-name (slot-value ov slot-name))))
(defmethod validate-all-slots ((ov object-validator)) ...)
Then have your `person` extend that, define setters, and have those call the validate methods:
(defclass person (object-validator)
((name :type string :setter set-person-name)
(age :type integer :setter set-person-age)
(slot-predicates :initform ((name . (lambda (val) (and (stringp val) (not (s-blank-p val)))))))))
(defmethod set-person-age :before ((p person) age)
(validate-slot-value p 'age age))
This is just a sketch and won't work as-is, but is there to illustrate the direction.
In CL, you'd make this a metaclass which would generate all the `:before` methods to do the validation, but EIEIO doesn't support those. You'd have to roll your own macro to generate them.
You seem to have a lot of questions about this, and I'm not sure repeated Reddit posts are the best way to get answers. I think you ought to read about [structures](https://www.gnu.org/software/emacs/manual/html_node/cl/Structures.html) and [EIEIO](https://www.gnu.org/software/emacs/manual/html_mono/eieio.html), and after that, ask any unanswered questions you have in #emacs on LiberaChat.