Search code examples
packagecommon-lispsbclccl

LISP cond answer no package


It is difficult to find an appropriate title because I do not understand why I have the following issue.

When I require my package, I would like to assign a specific function according to some packages. The idea is to set a variable as follow:

(cond ((find-package 'foo) (setf *special-function* #'foo:foo-function))
      ((find-package 'bar) (setf *special-function* #'bar:bar-function))
      (t (warn "The package FOO or BAR is required to enable the special function.")))

Then, the evaluation of this piece of code returns:

There is no package named "FOO" with CCL

Package FOO does not exist with SBCL

The main reason I want to do that is that it exists different packages which provide the same function, and I want to let the user be free to make its own choice by loading the package FOO or BAR (with a preference according to the order in the condition clauses).


Solution

  • Think about the execution/evaluation of the following form:

    (if (find-package 'foo)
        (foo:foo-function))
    

    Lisp

    1. reads the code
    2. and then evaluates the code.

    Your error happens in phase 1: Reading. The form can't be read, when the package does not exist.

    A typical way around it would be this:

    (if (find-package 'foo)
        (funcall (find-symbol "FOO-FUNCTION" "FOO")))
    

    We are then looking up the symbol at runtime. Note that function and package names are by default in uppercase.

    In your case you would need to call

    (symbol-function (find-symbol "FOO-FUNCTION" "FOO"))
    

    to get the function object. Note though that sometimes it's preferred to just get the symbol.

    funcall and apply can call global functions as function object or as symbol:

    (funcall 'sin 2.1d0)
    

    or

    (funcall #'sin 2.1d0)
    

    Thus when the thing needs to be called later, a symbol offers another source of indirection and will point to the current definition, where the function object can also be an older version of the function.