src/clos.lisp @ 443af0e76dd6
default tip
Add with-eof-handled
author |
Steve Losh <steve@stevelosh.com> |
date |
Sun, 23 Jun 2024 13:34:51 -0400 |
parents |
09232fd60df5 |
children |
(none) |
(in-package :losh.clos)
(defun build-slot-definition (conc-name slot-spec)
(destructuring-bind (name &rest slot-options) (ensure-list slot-spec)
`(,name
,@(unless (getf slot-options :initarg)
`(:initarg ,(alexandria:make-keyword name)))
,@(unless (or (getf slot-options :reader)
(getf slot-options :writer)
(getf slot-options :accessor))
`(:accessor ,(if conc-name
(symb conc-name name)
name)))
,@slot-options)))
(defmacro defclass* (name-and-options direct-superclasses slots &rest options)
"`defclass` without the tedium.
This is like `defclass`, but the `:initarg` and `:accessor` slot options will
automatically be filled in with sane values if they aren't given.
`name-and-options` can be a symbol or a list, which will be destructured
against `(name &key conc-name)`.
"
(destructuring-bind (name &key conc-name)
(ensure-list name-and-options)
`(defclass ,name ,direct-superclasses
,(mapcar (curry #'build-slot-definition conc-name) slots)
,@options)))
(defmacro define-condition* (name-and-options direct-superclasses slots &rest options)
"`define-condition` without the tedium.
This is like `define-condition`, but the `:initarg` and `:accessor` slot
options will automatically be filled in with sane values if they aren't given.
`name-and-options` can be a symbol or a list, which will be destructured
against `(name &key conc-name)`.
"
(destructuring-bind (name &key conc-name)
(ensure-list name-and-options)
`(define-condition ,name ,direct-superclasses
,(mapcar (curry #'build-slot-definition conc-name) slots)
,@options)))
(defun slot-value-or (object slot &optional default)
"Return the `slot-value` of `slot` in `object`, or `default` if unbound."
(if (slot-boundp object slot)
(slot-value object slot)
default))
(defmacro ensure-slot-value (object slot &optional default)
"Return the `slot-value` of `slot` in `object`, setting it to `default` if unbound."
(alexandria:once-only (object slot)
`(if (slot-boundp ,object ,slot)
(slot-value ,object ,slot)
(setf (slot-value ,object ,slot) ,default))))