代码之家  ›  专栏  ›  技术社区  ›  krzysz00

使CLOS对象可在Lisp中打印

  •  11
  • krzysz00  · 技术社区  · 15 年前

    如果要使通用Lisp中的CLOS对象可打印(可读打印),那么如何在不使用打印和读取以外的任何东西的情况下执行此操作?

    1 回复  |  直到 15 年前
        1
  •  5
  •   krzysz00    15 年前

    做这个有两个部分,至少在我的解决方案中是这样的,但是你需要这个功能(多亏了cl流行的人( 警告LGPL )

    (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* 在使用所有这些方法时,强烈建议使用。另外,请注意,循环关系没有经过测试