Common Lisp 格式的可重复差一问题

Repeatable off-by-one issue in Common Lisp's format

我有 format 的选项卡 ~VT 根据换行符 ~% 是在行首还是行尾表现不同,我想知道为什么。不同的是,当换行符在行尾时,制表位的第一个实例中似乎多了一个space。下面举例说明。示例中的唯一区别在于格式控制字符串:第一个示例中为 "~%~A~VT= ~A",第二个示例中为 "~A~VT= ~A~%"

示例 1:输出行开头的换行符

(let ((sb (make-array 0
                :element-type 'character
                :adjustable t
                :fill-pointer 0)))
           (mapcar (lambda (line)
                     (format sb "~%~A~VT= ~A" line 10 42))
                   '(a abcd asdf foobar g november))
           sb)
"
A        = 42
ABCD     = 42
ASDF     = 42
FOOBAR   = 42
G        = 42
NOVEMBER = 42"

此处的行为符合预期。

示例 2:输出行末尾的换行符

这个例子中要注意的是第一行,

A         = 42

其中比示例 1 中对应的行多 space:

A        = 42

由于前导双引号,它有点难看,这就是我将其删除的原因:帮助您更好地看到它们。 这在更大的示例上是可重复的,并且是从更大的程序中剥离出来的 MVE。

(let ((sb (make-array 0
                :element-type 'character
                :adjustable t
                :fill-pointer 0)))
           (mapcar (lambda (line)
                     (format sb "~A~VT= ~A~%" line 10 42))
                   '(a abcd asdf foobar g november))
           sb)
"A         = 42
ABCD     = 42
ASDF     = 42
FOOBAR   = 42
G        = 42
NOVEMBER = 42
"

大问题是 "why?" 我在 Mac 上使用 SBCL 1.3.1,还没有在其他实现上尝试过。这可能是一个错误,但它似乎更像是预期的行为,但我不明白它可能打算完成什么,而且我无法在格式的文档中找到解释。

我认为这是一个错误。我也可以使用 SBCL 1.3.1 在 Linux 上重现它。

~T 在某些情况下可能需要试探法(可能会失败)来确定当前列,但我想字符串的开头应该被视为第 0 列。

至少在我的电脑上,使用简单的 with-output-to-string 时似乎不会发生:

(with-output-to-string (s)
  (mapcar (lambda (line)
            (format s "~A~VT= ~A~%" line 10 42))
          '(a abcd asdf foobar g november)))

但是,当您将 pre-made 字符串提供给 with-output-to-string:

时,它确实会发生
(let ((sb (make-array 0
                      :element-type 'character
                      :adjustable t
                      :fill-pointer 0)))
  (with-output-to-string (s sb)
    (mapcar (lambda (line)
              (format s "~A~VT= ~A~%" line 10 42))
            '(a abcd asdf foobar g november))
    sb))