从循环内部格式返回

时间:2015-07-02 16:40:01

标签: loops format lisp common-lisp

我是一名Lisp noobie,在理解loopformat合并后的工作方式时遇到一些困难。

这符合我的预期:

(loop for i upto 2 do (format t "~a" "Badger")) ==> BadgerBadgerBadger NIL

这不是:

(loop for i upto 2 do (format nil "~a" "Badger")) ==> NIL

为什么第二个循环不返回BadgerBadgerBadger?我必须编写什么代码来提供此返回值?

2 个答案:

答案 0 :(得分:3)

返回值和打印值之间存在重要区别。有时这在REPL中会引起混淆,因为默认情况下会打印返回值:

CL-USER> (+ 1 1)    ; form *returns* 2
2                   ; and return value (2) is printed
CL-USER> (let () 
           (+ 1 1)  ; (+ 1 1) still returns 2, but
           nil)     ; the return value of the (let ...) is NIL
NIL                 ; so NIL is printed

现在,格式可以做一些不同的事情,具体取决于它的第一个参数。如果它的第一个参数是 t ,或者是一个流,那么它会将输出写入流并返回nil:

CL-USER> (format t "hello")
hello                         ; printed output
NIL                           ; return value from format

CL-USER> (let ()             
           (format t "hello") ; will print "hello"
           42)                ; but the whole form returns 42
hello                         ; printed output
42                            ; printed return value

当使用 nil 作为第一个参数调用format时,它会返回它作为字符串生成的输出:

CL-USER> (format nil "hello")
"hello"                           ; return value, not printed output

CL-USER> (let ()
           (format nil "hello")   ; returns "hello"
           42)                    ; but the whole form returns 42
42                                ; printed return value

现在,您可以收集循环结果,听起来您想使用格式生成字符串,然后收集这些字符串:

CL-USER> (loop for i upto 2 collect i)
(0 1 2)

CL-USER> (loop for i upto 2 collect (* 8 i))
(0 8 16)

CL-USER> (loop for i upto 2 collect (format nil "string number ~a" i))
("string number 0" "string number 1" "string number 2")

答案 1 :(得分:2)

这取决于format函数的第一个参数,称为 destination (参见manual):

  

如果 destination 是字符串,流或t,则结果为nil。否则,结果是包含'output'

的字符串

在第一种情况下,format写入标准输出(您看到三个" Budger")并返回NIL。但是,您没有看到那个值,而是loop返回的值NIL。事实上,LOOP中没有任何条款(如RETURN)可以返回与NIL不同的内容。

在第二种情况下,format返回字符串,但循环的值再次为NIL,这是整个表单的结果。

如果要返回格式的结果,可以编写:

(with-output-to-string (s)
   (loop for i upto 2 do (format s "~a" "Badger")))

通过这种方式,format功能"写"字符串流s,由with-output-to-string返回。