Search code examples
emacslispcommon-lispslime

Why is slime's "package" different from the inferior lisp?


I think I don't have a clear understanding of how slime is running lisp within Emacs.

Say I have a file with the following entries :-

(defpackage "TEST"
  (:use "COMMON-LISP"))
(in-package "TEST")
*package*

Now I compile/run these three with either of say

C-c C-c
C-x C-e

and I get the output :-

#<PACKAGE "TEST">

However, if I now switch buffers to the inferior lisp buffer and type

*package*

it gives me the output as

#<PACKAGE "COMMON-LISP-USER">

What gives? Using the slime commands above clearly does something but it doesn't seem to be affecting the main REPL loop for the inferior-lisp.


Solution

  • Global special variables

    Since global variables are using dynamic binding, one can rebind them:

    CL-USER> *package*
    #<The COMMON-LISP-USER package, 117/256 internal, 0/4 external>
    CL-USER> (defpackage "TEST"
               (:use "COMMON-LISP"))
    #<The TEST package, 0/16 internal, 0/16 external>
    CL-USER> (let ((*package* (find-package "TEST")))
               (intern "FOO"))
    

    So you don't need to set a global variable, you can rebind them.

    So something like SLIME can rebind them and execute the code for evaluation inside the rebound variable bindings:

    (let ((*package* (find-package "FOO")))
      (eval (read-from-string some-string-with-code)))
    

    Thread local global special variables

    One can also create threads, such that they have their own 'thread local' global variables:

    (sb-thread:make-thread (lambda (*package*)
                                        ...)
                           :arguments (list *package*))
    

    Above thread function will have its own *package* variable binding.

    IDE and globals

    Usually one would want the IDE to use the globals in the current listener thread (each listener thread should have its own globals).

    One also wants that evaluation from an editor Lisp code buffer uses the package from that buffer (typically the package defined on top or the package from the nearest IN-PACKAGE above in the code. The editor might also be able to set the package to use for the current Lisp code buffer.

    Then an IDE will use something like above during evaluation: rebinding the *package* variable and/or use multiple threads with their own *package* variable binding in each thread.

    IDE and multiple inferior Lisps

    Typically there will be only one inferior Lisp, but it might be possible to have multiple listeners into it. Some IDEs might also support more than one inferior Lisp.