Home > Mobile >  Returning a specific value from a function in common lisp?
Returning a specific value from a function in common lisp?

Time:11-26

I wrote a function with clsql. All it does is read the entire table. First it opens the connection, reads, then closes.

(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"))

With the disconnect expression last, I get T as the return value.

I want to get the value of clsql:print-query returned. However, the disconnection should go last because I need to make sure the connection closes.

I tried block and return-with, with no luck.

What is the best way to approach returning values

CodePudding user response:

To really make sure that a thing runs when leaving a scope use UNWIND-PROTECT.

(unwind-protect (read-the-file stream)
  (print "closing")
  (close stream))

Examples:

Here we make sure that some code runs after a form.

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

"doing-something" 
"ensuring safety" 

Here we see what happens if there is an error in the protected form:

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"     

Above shows that the PRINT call was running when leaving the scope.

If you only want to return the first forms value, one can use PROG1, which does not protect from errors.

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

"hello" 
0.14112

Above might be something like (but with some temp1 name which can not be inconflict with user code):

(let ((temp1 (sin 3)))
  (print "hello")
  temp1)

Your example with 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")))
  • Related