Если вы хотите сделать CLOS-объекты в common lisp пригодными для печати (читаемыми для печати), как вы можете это сделать, не используя ничего, кроме печати и чтения.
Сделать закрытые объекты доступными для печати в lisp
Ответы (1)
Для этого есть две части, по крайней мере, в моем решении, однако вам понадобится эта функция (спасибо ребятам из cl-prevalence за это (warn LLGPL)
(defun get-slots (object)
;; thanks to cl-prevalence
#+openmcl
(mapcar #'ccl:slot-definition-name
(#-openmcl-native-threads ccl:class-instance-slots
#+openmcl-native-threads ccl:class-slots
(class-of object)))
#+cmu
(mapcar #'pcl:slot-definition-name (pcl:class-slots (class-of object)))
#+sbcl
(mapcar #'sb-pcl:slot-definition-name (sb-pcl:class-slots (class-of object)))
#+lispworks
(mapcar #'hcl:slot-definition-name (hcl:class-slots (class-of object)))
#+allegro
(mapcar #'mop:slot-definition-name (mop:class-slots (class-of object)))
#+sbcl
(mapcar #'sb-mop:slot-definition-name (sb-mop:class-slots (class-of object)))
#+clisp
(mapcar #'clos:slot-definition-name (clos:class-slots (class-of object)))
#-(or openmcl cmu lispworks allegro sbcl clisp)
(error "not yet implemented"))
Затем для чтения вам нужно будет запустить этот фрагмент кода, который устанавливает 1/2 синтаксиса, который { type-of-object ((slot-name . slot-value) (slot-name . slot-value) ...)
(set-macro-character
#\{
#'(lambda (str char)
(declare (ignore char))
(let ((list (read-delimited-list #\} str t)))
(let ((type (first list))
(list (second list)))
(let ((class (allocate-instance (find-class type))))
(loop for i in list do
(setf (slot-value class (car i)) (cdr i)))
class)))))
Для печати используйте
(defmethod print-object ((object standard-object) stream)
(format stream "{ ~s ~s}" (type-of object)
(loop for i in (get-slots object)
collect (cons i (slot-value object i)))))
При использовании всех этих методов настоятельно рекомендуется *print-readably*
. Также обратите внимание, что круговые отношения не проверены
person
krzysz00
schedule
21.06.2010
у вас должно быть сбалансированное внешнее представительство. В настоящее время у вас есть начальный персонаж, но нет соответствующего закрывающего персонажа. Для чтения см., например, READ-DELIMITED-LIST. См. пример на lispworks.com/documentation/lw50/CLHS/Body/ f_rd_del.htm .
- person Rainer Joswig; 21.06.2010
возможно, вы правы, но это хорошо подходит для моих целей, поскольку должно быть ровно два объекта после {
- person krzysz00; 21.06.2010
да, но это смутит всех редакторов. s-выражения должны быть сбалансированы. В любом случае это простое изменение.
- person Rainer Joswig; 21.06.2010
формат предназначен для сброса, а затем вставки обратно без без редактирования
- person krzysz00; 21.06.2010
Да, но вы публикуете уродливый хак на Stackoverflow, и другие могут его скопировать. Если вы держите это только в своем программном обеспечении, работа с ним - только ваша проблема. Публикация нестандартного кода на Stackoverflow — не лучшая идея. Ваш код просто не является хорошим примером. Форматы на основе S-Expression сбалансированы, и Common Lisp уже дает пример с внешним форматом для структур.
- person Rainer Joswig; 22.06.2010
Здорово. Вы можете немного упростить форму и избавиться от двух let, заменив их одним DESTRUCTURING-BIND: (destructuring-bind (type. list) (read-delimited-list... Является ли переменная CLASS не лучше называться OBJECT или INSTANCE См. также приведенный выше пример в CLHS Возможно, вы захотите установить атрибут синтаксиса для символа }.
- person Rainer Joswig; 24.06.2010
что-то в моей кодовой базе сломалось, когда я попробовал это. Спасибо хоть. PS, текущее заклинание кода находится по адресу motm.svn.sourceforge.net/viewvc/motm/trunk/src/, а также, пока вы там, не стесняйтесь проверить остальную часть игры (motm.sourceforge.net)
- person krzysz00; 26.06.2010
Гораздо лучше использовать швабру ближе
- person Xach; 04.01.2011