Search code examples
importcommon-lisptemporal

Common Lisp: How to import symbols of other packages inside a lexical scope only?


I want to use some functions inside another package with a long name (e.g., "sb-bsd-sockets"), and I have to write this:

(defun myfun (...)
   (sb-bsd-sockets:socket-bind ...)
   (sb-bsd-sockets:socket-listen ...)
   ...)

Is there a way to import some of those symbols only available inside myfun (without any performance loss)?


Solution

  • The following is the first thing that popped into my head (a simple tree walk and replace of symbol names).

    It should be noted that the question was about importing symbols and the following does not do that. It simply adds the ugly package-name:: part for you.

    (defmacro with-symbols-from ((package-name &rest symbols) &body body)
      (let ((f-symbols (loop :for s :in symbols :collect 
                          (intern (symbol-name s) package-name))))
        `(progn
           ,@(loop :for symbol :in symbols :for f-symbol :in f-symbols 
                :with body = body
                :do (setf body (subst f-symbol symbol body :test #'eq))
                :finally (return body)))))
    

    Usage example:

    CL-USER> (with-symbols-from (:cffi foreign-alloc mem-aref)
               (let ((a (foreign-alloc :int)))
                 (setf (mem-aref a :int) 1)
                 (mem-aref a :int)))
    1
    

    The above expanded to:

    (PROGN
     (LET ((A (CFFI:FOREIGN-ALLOC :INT)))
       (SETF (CFFI:MEM-AREF A :INT) 1)
       (CFFI:MEM-AREF A :INT)))