以下是我在Hyperspec看到的一个例子:
(setq fstr (make-array '(0) :element-type 'base-char
:fill-pointer 0 :adjustable t))
(with-output-to-string (s fstr)
(format s "here's some output"))
然后fstr
持有here's some output
问:如果你想重新开始并在其中加入新内容,你怎么能对fstr
进行简单的清除/重置,即,不能连接更多吗?或者我是否只需要重做正在设置fstr
的顶级表达式?
答案 0 :(得分:8)
设置填充指针:
CL-USER 3 > (setq fstr (make-array '(0) :element-type 'base-char
:fill-pointer 0 :adjustable t))
""
CL-USER 4 > (with-output-to-string (s fstr)
(format s "here's some output"))
NIL
CL-USER 5 > fstr
"here's some output"
CL-USER 6 > (setf (fill-pointer fstr) 0)
0
CL-USER 7 > fstr
""
CL-USER 8 > (with-output-to-string (s fstr)
(format s "here's some more output"))
NIL
CL-USER 9 > fstr
"here's some more output"
您也可以调用adjust-array
来实际更改数组大小。
CL-USER 16 > (setf (fill-pointer fstr) 0)
0
CL-USER 17 > (adjust-array fstr 0)
""
答案 1 :(得分:6)
这里有两个相互作用的正交概念。第一个是矢量(字符串,一维数组等)可以有fill pointer:
填充指针 n。 (向量)与向量相关的整数 表示没有元素处于活动状态的索引。 (填写 指针是一个非负整数,不大于总数 向量中的元素。并非所有向量都有填充指针。)
当你查看字符串时,填充指针基本上是字符串的长度,但允许底层数组实际包含更多数据( 仍可访问 em>;这可能很重要,具体取决于应用程序。)
然后,有很多方法可以用填充指针操纵向量的内容。对于字符串,with-output-to-string提供了一个有用的字符串,它创建了一个字符输出,将字符输出发送到字符串。
with-output-to-string 创建一个字符输出流,执行一系列操作,可以将结果发送到此流,然后 关闭流。
因此,您可以使用(setf fill-pointer)“重置”字符串,并且可以使用 with-output-to-string 添加内容,以及其他方式:
(let ((str (make-array '(0)
:element-type 'base-char
:adjustable t
:fill-pointer 0)))
;; Temporarily create a character output stream that directs its
;; output to the underlying string that we created, and write "hello
;; world!" to it.
(with-output-to-string (s str)
(format s "hello world!"))
;; prints "hello world", sets the FILL-POINTER back to 0, and then
;; prints "".
(print str)
(setf (fill-pointer str) 0)
(print str)
;; But note that the underlying array
;; and the content that you put into
;; it are still available. While LENGTH
;; returns 0, ARRAY-TOTAL-SIZE reports
;; 12, and you can still just AREF to
;; get the old content.
(print (length str)) ;=> 0
(print (array-total-size str)) ;=> 12
(print (aref str 6)) ;=> #\w
;; update content using vector push extend, and print "abcde".
(vector-push-extend #\a str)
(vector-push-extend #\b str)
(vector-push-extend #\c str)
(vector-push-extend #\d str)
(vector-push-extend #\e str)
(print str) ;=> "abcde"
;; Or set the fill pointer manually, possibly setting content in the
;; array before or after. Note that you can (SETF AREF) elements in
;; the vector that aren't in the active portion. First, we confirm
;; that the fill pointer is at 5, then set an element at 8 (past the
;; fill pointer), then set the fill pointer to 10, and set an
;; element at 6 (before the fill pointer). All these changes affect
;; the vector contents.
(print (fill-pointer str)) ;=> 5
(setf (aref str 8) #\X)
(setf (fill-pointer str) 10)
(setf (aref str 6) #\Y)
(print str) ;=> "abcde YoXl"
)