在 SBCL 中读取带有类型槽的结构

Reading structures with typed slots in SBCL

考虑这个简单的代码示例:

(defstruct test
  (:example nil :type (simple-array single-float)))

(defparameter test-struct
  (make-test :example (make-array 10 :element-type 'single-float
                                     :initial-element 1.0)))

如我们所见,这里没有什么疯狂的地方,定义了一个带有单个槽的简单结构。我们还指定 :example 插槽是强类型,预期是单个浮点数数组。没有问题,一切正常。

让我们现在将 test-struct 写入文件:

(with-open-file (out "~/Desktop/out.test"
             :direction :output
             :if-exists :supersede)
  (format out "~s" test-struct))

同样,不出所料,我们在桌面上得到了一个漂亮的小文件,内容如下:

#S(TEST :EXAMPLE #(1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0))

然而,紧张情绪开始蔓延,因为我们注意到没有任何迹象表明这个特定的文字数组应该包含单个浮点数。带着这种怀疑,让我们尝试加载这个结构:

(defparameter loaded-struct
  (with-open-file (in "~/Desktop/out.test")
    (read in nil)))

我们到了,SBCL 愉快地将我们放入调试器:

问题是:有没有办法指示SBCL验证结构中的这个数组槽是有效类型并加载它?或者换句话说,是否可以在不借助构建自定义编写器和构造函数的情况下读取具有强类型插槽的结构?

如果您打印对象 可读:

(equalp test-struct
        (read-from-string 
          (with-output-to-string (o)
            (write test-struct :readably t :stream o))))
=> T ;; no error while reading the structure back

字符串是:

"#S(TEST
   :EXAMPLE #.(COERCE #(1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0)
                      '(SIMPLE-ARRAY SINGLE-FLOAT (*))))"

如果要使用format,请使用~W,而*print-readably*是T。