reddit / emacs

Add checks for structure fields

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.