Просто глядя на это, я не вижу причин, почему это должен быть макрос.Переписав его как функцию, вы избавите вас от многих проблем.
Использование WITH-SLOTS невозможно, как вы пытаетесь.Объект не известен вообще до времени выполнения.Компилятор должен знать слоты объекта уже во время компиляции.Вам нужно использовать SLOT-VALUE и искать значение слота во время выполнения.
Вы думаете, во многих отношениях слишком сложно, и ваш код немного запутан.Вы можете избавиться от путаницы, следуя простым правилам и избегая формулировок.
Давайте посмотрим на ваш код :
Во-первых, это не вспомогательный макрос, посколькучто следует за функцией.
;;helper macro
(defun class-slots-symbols (class-name)
Зачем брать имя класса?Почему бы не использовать сам класс?Классы являются первоклассными объектами.Написать функцию с очевидными интерфейсами.Элементарные функции должны работать с основными типами данных.
"Returns a list of the symbols used in the class slots"
В слотах классов символы не используются.слоты имеют имена, каждый может получить этот символ.
(mapcar 'closer-mop:slot-definition-name
(closer-mop:class-slots
(find-class class-name))))
Неудивительно, что у вас есть проблема с этим макросом.Это просто потому, что это должна быть функция, а не макрос.Макросы предназначены для преобразования исходного кода.Все, что вам нужно, это простые вычисления, поэтому макрос не требуется
;;macro that I am having difficulty with
(defmacro obj-to-hash (obj-inst)
Плохая формулировка: obj-inst.Либо назовите это объектом или экземпляром.Не оба.
"Reads an object, reflects over its slots, and returns a hash table of them"
Плохая документация: вы ничего не читаете.Чтение - это операция ввода-вывода, а в вашем коде - нет.Вы говорите об «объекте», но выше у вас есть что-то вроде «obj-inst».Зачем говорить об одном и том же двумя разными способами?Вы можете документировать, какие хеш-таблицы являются фактическими картами.От каких ключей к каким значениям?
`(let ((new-hash (make-hash-table))
new-hash - тоже плохое имя.По сути, это хеш-таблица.
(slot-list (class-slots-symbols (type-of ,obj-inst))))
Почему TYPE-OF, а затем в вызове вспомогательной функции FIND-CLASS?Common Lisp имеет CLASS-OF, который возвращает класс напрямую.
;;The slot-list needs to expand out correctly in the with-slots form
(with-slots (slot-list) obj-inst
Выше не будет работать, так как WITH-SLOTS ожидает имена слотов во время компиляции, а не список слотов.
(loop for slot in slot-list do ;and also here
(format t "~a~&" slot)
(hashset new-hash (string slot) slot)
HASHSET не нужен, если он не делает что-то особенное.Обычный способ установки значений - через SETF.SETF принимает форму для чтения места и форму для вычисления значения.Это все.Это работает для всех видов структур данных.Больше никогда не нужно вспоминать, как выглядит функция записи (имя, список параметров, ...).
))))
Вот моя версия :
Примечаниечто я использую пакет CLOS, вы можете использовать свой пакет CLOSER-MOP
(defun class-slots-symbols (class)
"Returns a list of the symbol names of the class slots"
(mapcar 'clos:slot-definition-name
(clos:class-slots class)))
Выше приведена простая функция, принимающая класс и возвращающая список имен слотов.
Далее,у нас есть простая функция, которая в этой форме была написана миллион раз в Common Lisp:
(defun object-to-hash (object)
"returns a hashtable with the object's slots as keys and slot-values as values"
(let ((hash-table (make-hash-table)))
(loop for slot-name in (class-slots-symbols (class-of object))
do (setf (gethash slot-name hash-table)
(string (slot-value object slot-name))))
hash-table))
Мы также можем переписать ее на немного более старый стиль Lisp:
(defun object-to-hash (object &aux (hash-table (make-hash-table)))
"returns a hashtable with the object's slots as keys
and string versions of the slot-values as values"
(dolist (slot-name (class-slots-symbols (class-of object)) hash-table)
(setf (gethash slot-name hash-table)
(string (slot-value object slot-name)))))
вышеэто намного проще и содержит всю путаницу с макросами, генерацией кода, информацией о времени компиляции и временем выполнения, ... удалена.Гораздо проще понять, поддерживать и отлаживать.