Reputation: 655
I'd like to be able to get my SBCL 1.4.5 (Linux x86_64) Emacs 'inferior-lisp-process' to evaluate a S-Expression (sexp) in some Emacs buffer that is not the 'slime' buffer - I have latest quicklisp and slime-2.20 .
I thought this was exactly the same issue as in : How to run Common Lisp code with Slime in Emacs Lisp but it is not - my issue is that when I try to run 'slime-eval' or any slime 'run in inferior-lisp-process' method ALL symbols seem to be being looked up in ONLY in the SWANK-IO-PACKAGE namespace :
In my Emacs '*scratch*' buffer:
(slime-eval '(symbolp '+) "CL-USER")
Produces a backtrace error:
The function SWANK-IO-PACKAGE::SYMBOLP is undefined.
[Condition of type UNDEFINED-FUNCTION]
Restarts:
0: [CONTINUE] Retry calling SWANK-IO-PACKAGE::SYMBOLP.
1: [USE-VALUE] Call specified function.
2: [RETURN-VALUE] Return specified values.
3: [RETURN-NOTHING] Return zero values.
4: [*ABORT] Return to SLIME's top level.
5: [ABORT] abort thread (#<THREAD "worker" RUNNING {100262C8E3}>)
Backtrace:
0: ("undefined function" SWANK-IO-PACKAGE::+)
1: (SB-INT:SIMPLE-EVAL-IN-LEXENV \
(SWANK-IO-PACKAGE::SYMBOLP (QUOTE SWANK-IO-PACKAGE::+)) \
#<NULL-LEXENV>)
2: (EVAL (SWANK-IO-PACKAGE::SYMBOLP (QUOTE SWANK-IO-PACKAGE::+)))
It makes no difference whether I do :
(slime-eval '(symbolp :+) "CL-USER")
OR
(slime-eval '(symbolp '+))
I still get the same error because '+ and :+ are always looked up only in the SWANK-IO-PACKAGE namespace.
I found this by simply trying to run, for my first test:
(slime-eval '(+ 2 2) "CL-USER")
which prints in the output buffer another backtrace
The function SWANK-IO-PACKAGE::+ is undefined.
[Condition of type UNDEFINED-FUNCTION]
I did try the code snippet from Question #22456086 :
(require 'slime)
(defun slrepl (str)
"Eval STR as Common Lisp code."
(unless (slime-current-connection)
(let ((wnd (current-window-configuration)))
(slime)
(while (not (and (slime-current-connection)
(get-buffer-window (slime-output-buffer))))
(sit-for 0.2))
(set-window-configuration wnd)))
(let (deactivate-mark)
(cadr (slime-eval `(swank:eval-and-grab-output ,str)))))
So doing:
(slrepl '(symbol-function '+))^X^E
Still results in :
The function SWANK-IO-PACKAGE::SYMBOL-FUNCTION is undefined.
[Condition of type UNDEFINED-FUNCTION]
Access to the default SB_INT namespace seems to be denied .
How to enable it for such cases ?
I'd like to be able to send forms to and read results from the same emacs inferior-lisp-process (sbcl) from any buffer, not just from the slime 'slime repl sbcl' buffer . Is there any way to do this?
Obviously, I can write an Emacs Lisp function to switch-to the slime repl buffer and evaluate in that buffer. Of course, all the above examples, eg. (eval '(symbolp '+)) , work fine in the slime-repl buffer. I guess there is no way around switching-to the slime-repl buffer?
This might clarify:
In 'scratch' :
(slime-eval '(SB-INT:symbolp 'SB-INT:+) "CL-USER")^X^E
In slime output buffer:
Invalid protocol message:
The symbol "SYMBOLP" is not external in the SB-INT package.
Line: 1, Column: 26, File-Position: 26
Stream: #<SB-IMPL::STRING-INPUT-STREAM {1002A1CD63}>
(:emacs-rex (SB-INT:symbolp (quote SB-INT:+)) "CL-USER" t 78)
So, in the slime-repl buffer, I can do:
CL-USER> (PROGN (IN-PACKAGE "COMMON-LISP-USER") (+ 2 2))
4
CL-USER> (PROGN (IN-PACKAGE "SB-IMPL") (symbol-function '+))
#<FUNCTION +>
CL-USER> (PROGN (IN-PACKAGE "SB-IMPL") (symbol-function '+))
#<FUNCTION +>
SB-IMPL> (PROGN (IN-PACKAGE "SB-INT") (symbol-function '+))
#<FUNCTION +>
But if I try to run the same 'slime-eval' function in any other buffer, eg. 'scratch' :
(slime-eval '(PROGN (COMMON-LISP-USER:IN-PACKAGE "COMMON-LISP-USER")
(symbol-function '+)) :COMMON-LISP-USER)
Invalid protocol message:
The symbol "IN-PACKAGE" is not external in the
COMMON-LISP-USER package.
Line: 1, Column: 46, File-Position: 46
I have tried ALL the likely PACKAGE names listed above in the slime-eval with same results. The same thing happens whether I use the 'slrepl' code snippet or just plain slime-eval - no lisp standard syntax symbols are available. Do I need to load the lisp syntax table or something ?
RE: can I switch to slime repl buffer and do it ? : NO ! :
(require 'slime)
(let ((slbuf (get-buffer "*slime-repl sbcl*")))
(if (eq nil slbuf)
(error "please start slime (M-x slime)")
(progn (set-buffer slbuf)(slime-eval '(+ 2 2) "COMMON-LISP-USER"))
)
)^X^E
Still results in :
The function SWANK-IO-PACKAGE::+ is undefined.
[Condition of type UNDEFINED-FUNCTION]
I am a rusty / returning LISP user and new to SBCL and slime . I'd really like to integrate Emacs' great Editing and File management & interacation facilitties with external CL XML & HTML generation & parsing tools. But to start, I'd just like to get to the root of this problem...
Upvotes: 3
Views: 1057
Reputation: 139261
Common Lisp symbols like +
and symbolp
are in the COMMON-LISP
package. Short name CL
. These symbols are usually not exported from package CL-USER
. Thus symbolp
can be referenced as cl:symbolp
. These symbols are accessible in package CL-USER
, but not exported from there. Thus you can also reference cl:symbolp
as cl-user::symbolp
-> note the two colons.
CALLING IN-PACKAGE
in a form does not have an effect on the form itself, since the form is already read. Though it has an effect calling reader functions or functions like find-symbol
.
CL-USER 5 > (defpackage "FOO" (:use))
#<The FOO package, 0/16 internal, 0/16 external>
CL-USER 6 > (progn (in-package "FOO")
(list 'bar (read-from-string "BAR")))
(COMMON-LISP-USER::BAR BAR) ; we now print from package "FOO"
Using SLIME-EVAL in Emacs Lisp
Best use it with a form, that reads the expression on the Common Lisp side and does not involve the Emacs Lisp reader/printer:
ELISP> (slime-eval '(cl:eval (cl:read-from-string "(+ 1 2)")) "CL-USER")
3 (#o3, #x3, ?\C-c)
ELISP> (slime-eval '(cl:eval (cl:read-from-string "'foo")) "CL-USER")
common-lisp-user::foo
But here you see that the result is brought back into Emacs Lisp via the Emacs Lisp reader - where packages don't exist.
Thus SLIME-EVAL
makes very little sense as a simple remote execution interface...
Upvotes: 2
Reputation: 655
This now works! Thanks !
(require 'slime)
(defun CL$ (str)
(let ((slbuf (get-buffer "*slime-repl sbcl*")))
(if (eq nil slbuf)
(error "Please start slime (M-x slime).")
(progn
(set-buffer slbuf)
(slime-eval str "CL")
)
)
)
)
(CL$ '(cl:+ 2 2))
=> 4
But I don't fully understand why I have to prepend all symbols with CL or why this still does not work:
(slime-eval '(+ 2 2) "CL")
but this does: (slime-eval '(cl:+ 2 2) "CL")
I thought the third parameter was meant to be made into the current package? So why do I have to append 'cl' to every symbol . But thanks for the help, and an otherwise great slime + sbcl .
Upvotes: 1