打印并报告输出的字符数

时间:2018-09-05 18:20:40

标签: common-lisp

鉴于我正在调用write以输出某些值(可能是原子,列表,点对),有没有办法找出要写入多少个字符?是在通话之前还是之后,还是使用一些类似的功能?

2 个答案:

答案 0 :(得分:4)

如果您正在写file-stream, 您可以使用file-position write之前和之后。

如果信息流中没有位置的概念(例如broadcast-stream),则必须求助于 到write-to-stringwrite-string

(defun write-and-count (object &rest args &key stream &allow-other-keys)
  "Write object to stream and return the number of characters written."
  (let ((start (ignore-errors (file-position stream))))
    (if start
        (progn              ; file stream
          (apply #'write object args)
          (- (file-position stream) start))
        (progn              ; something more complex
          (remf args :stream)
          (length (write-string (apply #'write-to-string object args) stream))))))

(with-open-file (s "foo" :direction :output)
  (write-and-count '(1 2 3) :stream s))
==> 7
(write-and-count '(1 2 3) :stream *standard-input*)
(1 2 3)    ; output
==> 7      ; return value
(write-and-count '(1 2 3))
(1 2 3)    ; output
==> 7      ; return value

注释

  1. file-position方法只是对大型对象的优化。
  2. remf需要避免illegal keyword/value pair中的write-to-string错误。
  3. 流可能很棘手;不能保证(write x :stream s)等同于(write-string (write-to-string x) s)。考虑一下(虽然不是正式的,但得到了广泛实施的)Gray streams:如果您写了一个broadcast-stream,它会广播到一个普通的file-stream和一个pretty-printing Gray stream,将{<3}}个不同个字符添加到两个流中。您希望返回的字符数是多少?第一算?第二?他们的总和?

答案 1 :(得分:2)

更复杂的方法是使用灰色流,这是David N. Gray曾经提出的基于CLOS的I / O流变体。许多实现以某种方式支持它。例如,可以编写新的流类并为输出函数编写:after方法,这些方法将记录所写字符的数量。

灰色流提供基于CLOS的可扩展I / O流。

如果人们已经编写了这样的功能,我不会感到惊讶...

有关几种实现的兼容性层,请参见trivial gray streams