7.3 输出 (Output)

三个最简单的输出函数是 prin1 , princ 以及 terpri 。这三个函数的最后一个参数皆为选择性的流参数,缺省是 *standard-output*

prin1princ 的差别大致在于 prin1 给程序产生输出,而 princ 给人类产生输出。所以举例来说, prin1 会印出字符串左右的双引号,而 princ 不会:

  1. > (prin1 "Hello")
  2. "Hello"
  3. "Hello"
  4. > (princ "Hello")
  5. Hello
  6. "Hello"

两者皆返回它们的第一个参数 (译注: 第二个值是返回值) ── 顺道一提,是用 prin1 印出。 terpri 仅印出一新行。

有这些函数的背景知识在解释更为通用的 format 是很有用的。这个函数几乎可以用在所有的输出。他接受一个流 (或 tnil )、一个格式化字符串 (format string)以及零个或多个额外的参数。格式化字符串可以包含特定的格式化指令 (format directives),这些指令前面有波浪号 ~ 。某些格式化指令作为字符串的占位符 (placeholder)使用。这些位置会被格式化字符串之后,所给入参数的表示法所取代。

如果我们把 t 作为第一个参数,输出会被送至 *standard-output* 。如果我们给 nilformat 会返回一个它会如何印出的字符串。为了保持简短,我们会在所有的示例里演示怎么做。

由于每人的观点不同, format 可以是令人惊讶的强大或是极为可怕的复杂。有大量的格式化指令可用,而只有少部分会被大多数程序设计师使用。两个最常用的格式化指令是 ~A 以及 ~% 。(你使用 ~a~A 都没关系,但后者较常见,因为它让格式化指令看起来一目了然。) 一个 ~A 是一个值的占位符,它会像是用 princ 印出一般。一个 ~% 代表着一个换行符 (newline)。

  1. > (format nil "Dear ~A, ~% Our records indicate..."
  2. "Mr. Malatesta")
  3. "Dear Mr. Malatesta,
  4. Our records indicate..."

这里 format 返回了一个值,由一个含有换行符的字符串组成。

~S 格式化指令像是 ~A ,但它使用 prin1 印出对象,而不是 princ 印出:

  1. > (format t "~S ~A" "z" "z")
  2. "z" z
  3. NIL

格式化指令可以接受参数。 ~F 用来印出向右对齐 (right-justified)的浮点数,可接受五个参数:

  1. 要印出字符的总数。缺省是数字的长度。
  2. 小数之后要印几位数。缺省是全部。
  3. 小数点要往右移几位 (即等同于将数字乘 10)。缺省是没有。
  4. 若数字太长无法满足第一个参数时,所要印出的字符。如果没有指定字符,一个过长的数字会尽可能使用它所需的空间被印出。
  5. 数字开始印之前左边的字符。缺省是空白。

下面是一个有五个参数的罕见例子:

  1. ? (format nil "~10,2,0,'*,' F" 26.21875)
  2. " 26.22"

这是原本的数字取至小数点第二位、(小数点向左移 0 位)、在 10 个字符的空间里向右对齐,左边补满空白。注意作为参数给入是写成 '* 而不是 #\* 。由于数字塞得下 10 个字符,不需要使用第四个参数。

所有的这些参数都是选择性的。要使用缺省值你可以直接忽略对应的参数。如果我们想要做的是,印出一个小数点取至第二位的数字,我们可以说:

  1. > (format nil "~,2,,,F" 26.21875)
  2. "26.22"

你也可以忽略一系列的尾随逗号 (trailing commas),前面指令更常见的写法会是:

  1. > (format nil "~,2F" 26.21875)
  2. "26.22"

警告:format 取整数时,它不保证会向上进位或向下舍入。就是说 (format nil "~,1F" 1.25) 可能会是 "1.2""1.3" 。所以如果你使用 format 来显示资讯时,而使用者期望看到某种特定取整数方式的数字 (如: 金额数量),你应该在印出之前先显式地取好整数。