a
Есть вот такая форма которая мне очень нравится:
(defmacro mk-calculation (plist &body body)
`(let ((params ,plist)
(runner-string (quote ,@body))
(status 'new))
(labels ((all-params () params)
(get-param (key) (getf params key))
(set-param (key val) (setf (getf params key) val))
(get-status () status)
(set-status (sym) (setf status sym)))
(lol:dlambda
(:get (key) (get-param key))
(:status () status)
(:show-runner () runner-string)
(:run () (progn ,@body
(setf status 'finished)))
(t () (cons (cons 'calculation status) (list params)))))))
А именно: замыкание вокруг списка параметров (любых там), который должен быть обработан команой
:run
, в принципе один раз и с кучей сайд-эффектов. Чтобы можно было сериализовать и перезапускать это чудо, в runner-string
пишется quote еще не скомпилированного body; в labels
опред. сеттеры для стэйта этого_конкретного_объекта.А вопрос, почему такой подход называют "quick AND dirty", и какой профит можно ожидать от использования CLOS+MOP вместо него?
• потому, что если понадобится расширять это дело, то могут начаться проблемы, и полноценное читаемое их решение приведет к переимплементации части CLOS или, может быть, к имплементации struct'ов, но не настолько эффективной как встроенные struct'ы. При этом бонусы по эффективности по ср. с CLOS таким подходом можно получить, это да.
• потому что, например, число аргументов в «методах» не учитывается в dlambda, хотя могло бы, и в результате этого этим интерфейсом легче воспользоваться так, что это вызовет ошибку, причем сообщение о ней будет малоинформативным. С CLOS или struct'ами это не так.
Чтоб ответить на вопрос «как выглядела бы альтернатива с CLOS», я все-таки спрошу: как именно предлагается производить сериализацию?