(漂亮)在Common Lisp

时间:2016-01-20 09:41:01

标签: printing lisp common-lisp read-eval-print-loop sbcl

如果我有一个包含例如一些填充向量的插槽的类,则通常会出现问题。如果我想让这个类的对象或多或少透明,我会为它实现print-object。在这里,我面临着这个问题:

  1. 如果我在一行中打印所有内容,REPL的启发式方法不足以确定如何在多行中排列可打印部分,导致所有内容向右移动(参见下面的示例)。
  2. 如果我决定手动将输出拆分为多行,我会遇到如何正确缩进所有内容的问题,这样如果此对象是另一个对象的一部分,则会保留缩进(请参阅下面的示例以获得更清晰)。
  3. 这是代码。考虑两个类:

    (defclass foo ()
      ((slot1 :initarg :slot1)
       (slot2 :initarg :slot2)))
    
    (defclass bar ()
      ((foo-slot :initarg :foo)))
    

    我有以下几个例子:

    (defparameter *foo*
      (make-instance 'foo
        :slot1 '(a b c d e f g h i j k l m n o p q r s t u v)
        :slot2 #(1 2 3 4 5 6 7 8)))
    
    
    (defparameter *bar*
      (make-instance 'bar
        :foo *foo*))
    

    我想看到的是这样的:

    > *bar*
    #<BAR
      foo-slot = #<FOO
                    slot1 = (A B C D E F G H I J K L M N O P Q R S T U V)
                    slot2 = #(1 2 3 4 5 6 7 8)>>
    

    案例1:在一行中打印所有内容

    这些类的print-object定义可以是这样的:

    (defmethod print-object ((obj foo) out)
      (with-slots (slot1 slot2) obj
        (print-unreadable-object (obj out :type t)
          (format out "slot1 = ~A slot2 = ~A" slot1 slot2))))
    
    (defmethod print-object ((obj bar) out)
      (with-slots (foo-slot) obj
        (print-unreadable-object (obj out :type t)
          (format out "foo-slot = ~A" foo-slot))))
    

    然而,他们的可打印表示不太理想:

    > *foo*
    #<FOO slot1 = (A B C D E F G H I J K L M N O P Q R S T U V) slot2 = #(1 2 3 4 5
                                                                          6 7 8)>
    
    > *bar*
    #<BAR foo-slot = #<FOO slot1 = (A B C D E F G H I J K L M N O P Q R S T U V) slot2 = #(1
                                                                                           2
                                                                                           3
                                                                                           4
                                                                                           5
                                                                                           6
                                                                                           7
                                                                                           8)>>
    

    案例2:尝试多行打印

    使用多行打印,我不知道如何控制缩进:

    (defmethod print-object ((obj foo) out)
      (with-slots (slot1 slot2) obj
        (print-unreadable-object (obj out :type t)
          (format out "~%~Tslot1 = ~A~%~Tslot2 = ~A" slot1 slot2))))
    
    (defmethod print-object ((obj bar) out)
      (with-slots (foo-slot) obj
        (print-unreadable-object (obj out :type t)
          (format out "~%~Tfoo-slot = ~A" foo-slot))))
    

    因此,*foo*打印正常,但*bar*不是:

    > *foo*
    #<FOO 
      slot1 = (A B C D E F G H I J K L M N O P Q R S T U V)
      slot2 = #(1 2 3 4 5 6 7 8)>
    *bar*
    #<BAR 
      foo-slot = #<FOO 
      slot1 = (A B C D E F G H I J K L M N O P Q R S T U V)
      slot2 = #(1 2 3 4 5 6 7 8)>>
    

    在过去,我尝试使用print-indent,但没有成功(我看不出任何效果,可能没有正确使用它,SBCL 1.2.14)。

    是否有(最好是简单的)方法来解决这个问题?

1 个答案:

答案 0 :(得分:7)

尝试这样的事情(可能需要更多抛光):

For loop

它使用(defmethod print-object ((obj foo) out) (with-slots (slot1 slot2) obj (print-unreadable-object (obj out :type t) (format out "~<~:_slot1 = ~A ~:_slot2 = ~A~:>" (list slot1 slot2))))) (defmethod print-object ((obj bar) out) (with-slots (foo-slot) obj (print-unreadable-object (obj out :type t) (format out "~<~:_foo-slot = ~A~:>" (list foo-slot))))) ~<,它们是逻辑块的格式化操作。然后它使用~:>,这是一个条件换行符。您应该阅读relevant hyperspec section