How to evaluate Common Lisp code in non-slime buffers? - emacs

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...

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...

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 .

Related

Why this macro to pretty print macro expansions in Common Lisp does not work? What are the alternatives tools for this?

I am trying to learn Common Lisp with the book Common Lisp: A gentle introduction to Symbolic Computation. In addition, I am using SBCL, Emacs, and Slime.
In chapter 14, the last one, the author covers macros. He presents a tool called PPMX which stands for: ‘‘Pretty Print Macro eXpansion’’.
With this tool, you can do:
> (ppmx (incf a))
Macro expansion:
(SETQ A (+ A 1))
The tool is self-contained since the book provides the code definition for it:
(defmacro ppmx (form)
"Pretty prints the macro expansion of FORM."
‘(let* ((exp1 (macroexpand-1 ’,form))
(exp (macroexpand exp1))
(*print-circle* nil))
(cond ((equal exp exp1)
(format t "~&Macro expansion:")
(pprint exp))
(t (format t "~&First step of expansion:")
(pprint exp1)
(format t "~%~%Final expansion:")
(pprint exp)))
(format t "~%~%")
(values)))
Unfortunately, I cannot run it because the compilation does not work. The Slime's REPL throws this error:
ch-14.lisp:3:33:
read-error:
READ error during COMPILE-FILE:
Comma not inside a backquote.
Line: 3, Column: 33, File-Position: 101
Stream: #<SB-INT:FORM-TRACKING-STREAM for "file /tmp/slimeD4xBr3" {10036BFC63}>
Compilation failed.
The comma and left single quote look different in emacs than in SO:
I have had some problems when copying the code from the book to emacs. It was basically inserting ' instead of the left single quote.
1 - Is there a way to fix this?
2 - The book was written in the late 1980s. Thus, I bet there are better tools now. Does Slime or SBCL offer some command to pretty print macro expansions? Maybe a library or another package?
Thanks.
Following #barmar's advice, the user just need to write in the REPL:
CL-USER> *print-pretty*
T
CL-USER> (macroexpand (setf a 1)) ;without the quote it does not work
1
NIL
CL-USER> (macroexpand '(setf a 1)) ;with the quote it does
(SETQ A 1)
T

evaluating file inside let

If my-variable is globally undefined, and my-file.el uses it,
;; -*- lexical-binding: t; -*-
(let((my-variable 1))
(load "/path/to/my-file.el"))
reports an error:
Debugger entered--Lisp error: (void-variable my-variable)
On the other hand,
;; -*- lexical-binding: t; -*-
(defvar my-variable 11)
(let((my-variable 1))
(load "/path/to/my-file.el"))
works using locally defined value 1.
Why do I have to use defvar?
PS: my-file.el can be a one-liner:
(1+ my-variable)
The file that the let is in is probably using lexical-binding, which means that for:
(let ((my-variable 1))
(load "/path/to/my-file.el"))
There is nothing in the lexical scope of my-variable which uses it.
If you byte-compiled the file, it would tell you:
Warning: Unused lexical variable ‘my-variable’
Adding the defvar marks it as a dynamic scope variable, in which case the code evaluated while my-file.el is being loaded will also see the let-bound value.
Note that (defvar my-variable) with no value is also sufficient to do that, and is what you should use if this isn't where the variable is supposed to be defined.
See Using Lexical Binding:
Lexical binding is also enabled in Lisp Interaction and IELM mode, used in the scratch and ielm buffers, and also when evaluating expressions via M-: (eval-expression) and when processing the --eval command-line options of Emacs (see Action Arguments in The GNU Emacs Manual) and emacsclient (see emacsclient Options in The GNU Emacs Manual).
So, if you evaluate the let in the *scratch* buffer, it uses lexical binding, which means the value of the variable is only bound to the lexical context, i.e. it isn't preserved when loading a different file.
Another possibility is you run it from an .el file with lexical binding turned on. If you turn it off, it should work the way you expected. Use the buffer local variable lexical-binding to enable or disable it.
[Not an answer but I did not want to edit the OP's question willy-nilly with what I see (and it's too long for a comment). I just provide a description of how I reproduce the problem since #choroba seems to get different results]
I have this in /tmp/my-file.el:
(if (= my-variable 1) (message "Yes") (message "N
I start emacs with emacs -Q and evaluate the following in the *scratch* buffer (sneaking in the version info):
(emacs-version '(4))
GNU Emacs 28.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.25, cairo version 1.16.0)
of 2021-03-07nil
(let ((my-variable 1))
(message (format "%d" my-variable))
(load "/tmp/foo.el"))
and I get the following backtrace:
Debugger entered--Lisp error: (void-variable my-variable)
(= my-variable 1)
(if (= my-variable 1) (message "Yes") (message "No"))
eval-buffer(#<buffer *load*> nil "/tmp/foo.el" nil t) ; Reading at buffer position 54
load-with-code-conversion("/tmp/foo.el" "/tmp/foo.el" nil nil)
load("/tmp/foo.el")
(let ((my-variable 1)) (message (format "%d" my-variable)) (load "/tmp/foo.el"))
(progn (let ((my-variable 1)) (message (format "%d" my-variable)) (load "/tmp/foo.el")))
eval((progn (let ((my-variable 1)) (message (format "%d" my-variable)) (load "/tmp/foo.el"))) t)
elisp--eval-last-sexp(t)
eval-last-sexp(t)
eval-print-last-sexp(nil)
funcall-interactively(eval-print-last-sexp nil)
call-interactively(eval-print-last-sexp nil nil)
command-execute(eval-print-last-sexp)
I get exactly the same result with the emacs that is packaged in my distro (Fedora 33): GNU Emacs 27.1 (build 1, x86_64-redhat-linux-gnu, GTK+ Version 3.24.22, cairo version 1.16.0) of 2020-08-20.

How can I get syntax highlighting for common lisp in SLIME's REPL?

I want to learn Common Lisp and have installed emacs (24.3) and slime via the emacs package manager.
In the slime REPL syntax highlighting doesn't work. When I start Lisp-Mode (while in the slime REPL) on the other hand, the values of the expressions don't get printed anymore (when I type, say "Hello World" and hit enter I get a new line instead of the value of the expression.
(If I open lisp files syntax highlighting works)
this works for me
(https://comp.emacs.narkive.com/AWoywbFs/tweaking-slime):
(defvar slime-repl-font-lock-keywords lisp-font-lock-keywords-2)
(defun slime-repl-font-lock-setup ()
(setq font-lock-defaults
'(slime-repl-font-lock-keywords
;; From lisp-mode.el
nil nil (("+-*/.<>=!?$%_&~^:#" . "w")) nil
(font-lock-syntactic-face-function
. lisp-font-lock-syntactic-face-function))))
(add-hook 'slime-repl-mode-hook 'slime-repl-font-lock-setup)
(defadvice slime-repl-insert-prompt (after font-lock-face activate)
(let ((inhibit-read-only t))
(add-text-properties
slime-repl-prompt-start-mark (point)
'(font-lock-face
slime-repl-prompt-face
rear-nonsticky
(slime-repl-prompt read-only font-lock-face intangible))))))

Emacs: the code in the body of a defun or defmacro cannot refer to surrounding lexical variables?

Update 2013 May: As of GNU Emacs 24.3.1, (let .. (defun..)) bytecompiles just fine without warning and the bytecompiled code works the same as not-compiled code. Just don't forget to add the file variable lexical-binding: t to the file to be bytecompiled. Workarounds at the end of this question is now not necessary.
Lexical Binding - Emacs Lisp Manual has this paragraph:
Note that functions like symbol-value, boundp, and set only retrieve or modify a variable's dynamic binding (i.e. the contents of its symbol's value cell). Also, the code in the body of a defun or defmacro cannot refer to surrounding lexical variables.
I am not sure if I am getting the meaning of the second sentence right. In the following code which should be run in lexical binding mode, the code in the body of a defun is successfully referring to the lexical binding value of the name n.
(let ((n 0))
(defun my-counter ()
(incf n)))
(my-counter) ;; 1
(my-counter) ;; 2
Is the sentence simply saying that (let .. (defun ..)) is a bad practice?
Workarounds:
;; -*- lexical-binding: t -*-
;; a way to define the counter function without byte-compile error or warning
(defvar my--counter-func
(let ((n 0))
(lambda ()
(setq n (1+ n)))))
(defun my-counter ()
(funcall my--counter-func))
;; another way to define the counter function, again without byte-compile error or warning
(fset 'my-another-counter
(let ((n 0))
(lambda ()
(setq n (1+ n)))))
And here's the code for testing the above code:
;; run:
;; emacs -q --load path-to-the-el-file-of-this-code.el
(load "path-to-file-defining-my-counter.elc") ;; loading the ELC file to test if byte-compiled code runs as expected.
(print (my-counter)) ;; 1
(print (my-counter)) ;; 2
(print (my-another-counter)) ;; 1
(print (my-another-counter)) ;; 2
The code does not byte-compile well at least in Emacs 24.1.1. I saved the following code in the foo.el file, which uses setq in place of incf in order to avoid any possible effects by the cl library:
;; -*- lexical-binding: t -*-
(let ((n 0))
(defun my-counter ()
(setq n (1+ n))))
When I tried to byte-compile it (M-x byte-compile-filefoo.el), I got the following warning messages:
foo.el:3:1:Warning: Function my-counter will ignore its context (n)
foo.el:3:1:Warning: Unused lexical variable `n'
foo.el:5:11:Warning: reference to free variable `n'
foo.el:5:17:Warning: assignment to free variable `n'
All of the messages are indicating that the code in the body of the defun construct cannot refer to the surrounding lexical variable n as the manual claims.
Actually, when I loaded the byte-compiled code (M-x load-filefoo.elc) and evaluted the (my-counter) form, I got the following erorr:
Debugger entered--Lisp error: (void-variable n)
...
Unfortunately, I'm not sure why the code appears to work when evaluated in the form of source code.
As I replied on gnu.emacs.help, you can use (defalias 'foo (lambda ...)) to work around that limitation.
And that limitation is lifted in Emacs's development code.
It's perfectly fine to refer to variables in lexical scope(*) from within a defun, just as you are doing above, and just as the "my-ticker" example on that manual page does as well.
Either I am missing something the line in the manual that says:
the code in the body of a defun or defmacro cannot refer to
surrounding lexical variables.
should say something more like:
code in the body of a defun can only access lexical variables if they are defined within the same lexical scope.
NOTE: There are comments in the other answers about problems byte-compiling this kind of code. Those should be fixed in the latest emacs. I've verified in v24.2.50.1 that this byte compiles and loads correctly.

How can I distinguish scheme dialects in org-babel code blocks?

Evaluating this code (C-c C-c):
#+begin_src scheme
(andmap + '(1 2 3) '(4 5 6))
#+end_src
leads to the following babel error:
ERROR: Unbound variable: andmap
The cause: babel evaluated the code with Guile instead of Racket. How can I tell Babel to execute code using Racket, not Guile?
http://terohasu.net/blog/2011-09-08-on-racket-support-in-emacs-org-mode.html describes a way:
When configuring Emacs to set things up I wasn’t familiar with Babel
or any of the solutions for evaluating Scheme code under Emacs for
that matter. After some looking at Babel and Inferior
Lisp,
I didn’t manage to configure Babel to invoke Racket for evaluating a
code listing. Instead I resorted to replacing the Babel code for
Scheme support (in the ob-scheme.el) with basically just the following
code:
(defun org-babel-execute:scheme (body params)
(let* ((tangle (cdr (assoc :tangle params)))
(script-file
(if (string-equal tangle "no")
(org-babel-temp-file "org-babel-" ".rkt")
tangle)))
(with-temp-file script-file
(insert body))
(let* ((pn (org-babel-process-file-name script-file))
(cmd (format "racket -u %s" pn)))
(message cmd)
(shell-command-to-string cmd)
)))
This solution creates a new Racket instance for every evaluation, and
hence is not as efficient as an Inferior Lisp based solution (or
similar), but it works, is more straightforward, avoids Racket issues
such as specifying the correct module context for evaluating the code,
and the evaluation context is always “clean” as a new Racket instance
is used.