从 Common Lisp 中的函数返回特定值?

Vin*_*inn 1 function sbcl common-lisp

我用clsql写了一个函数。它所做的只是读取整个表。首先它打开连接,读取,然后关闭。

(defun select()
  (clsql:connect "new.db" :database-type :sqlite3)

  (clsql:print-query
   "select * from contacts"
   :titles '("id" "firstname" "email" "company" "firstline" "status"))
  (clsql:disconnect :database "new.db"))

Run Code Online (Sandbox Code Playgroud)

有了disconnect最后一个表达式,我得到T返回值。

我想得到的值clsql:print-query返回的值。但是,断开连接应该最后进行,因为我需要确保连接关闭。

我尝试block过并且return-with,但没有运气。

接近返回值的最佳方法是什么

Rai*_*wig 5

要真正确保事物在离开范围时运行,请使用UNWIND-PROTECT.

(unwind-protect (read-the-file stream)
  (print "closing")
  (close stream))
Run Code Online (Sandbox Code Playgroud)

例子:

这里我们确保一些代码在表单之后运行。

CL-USER 41 > (unwind-protect (progn  ; protected form
                               (print "doing-something")
                               (values))
               (print "ensuring safety"))  ; this WILL run

"doing-something" 
"ensuring safety" 
Run Code Online (Sandbox Code Playgroud)

下面我们看看如果受保护的表单出现错误会发生什么:

CL-USER 42 > (unwind-protect (progn
                               (error "foo")
                               (print "doing-something")
                               (values))
               (print "ensuring safety"))

Error: foo
  1 (abort) Return to top loop level 0.

Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.

CL-USER 43 : 1 > :c 1                 ; ABORTING

"ensuring safety"     
Run Code Online (Sandbox Code Playgroud)

上图显示离开作用域时 PRINT 调用正在运行。

如果您只想返回第一个表单值,可以使用 PROG1,它不能防止错误。

CL-USER 44 > (prog1
                 (sin 3)
               (print "hello"))

"hello" 
0.14112
Run Code Online (Sandbox Code Playgroud)

上面可能类似于(但有一些 temp1 名称,不能与用户代码冲突):

(let ((temp1 (sin 3)))
  (print "hello")
  temp1)
Run Code Online (Sandbox Code Playgroud)

您的 UNWIND-PROTECT 示例

(defun select()
  (clsql:connect "new.db" :database-type :sqlite3)
  (unwind-protect
      (clsql:print-query
       "select * from contacts"
       :titles '("id" "firstname" "email" "company" "firstline" "status"))
    (clsql:disconnect :database "new.db")))
Run Code Online (Sandbox Code Playgroud)