I installed ltk to Steel Bank Common Lisp with asdf-install, but I can't even start using it V_V. The code below is the simplest example in the documentation, and is copied almost verbatim.
(asdf:operate 'asdf:load-op :ltk)
(defun hello-1()
(with-ltk ()
(let ((b (make-instance 'button
:master nil
:text "Press Me"
:command (lambda ()
(format t "Hello World!~&")))))
(pack b))))
(hello-1)
This is the error message I get from sbcl:
> ; in: LAMBDA NIL
; (PACK B)
;
; caught STYLE-WARNING:
; undefined function: PACK
; (WITH-LTK NIL
; (LET ((B (MAKE-INSTANCE 'BUTTON :MASTER NIL :TEXT "Press Me" :COMMAND #)))
; (PACK B)))
;
; caught STYLE-WARNING:
; undefined function: WITH-LTK
;
; compilation unit finished
; Undefined functions:
; PACK WITH-LTK
; caught 2 STYLE-WARNING conditions
debugger invoked on a SIMPLE-ERROR in thread #<THREAD "initial thread" RUNNING {1002A57B61}>:
There is no class named BUTTON.
Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SB-PCL::FIND-CLASS-FROM-CELL BUTTON NIL T)
You have to import the symbols into the package you want it to work in.
The generic "user" package is cl-user, and a "virgin" image will put you there. In order to import the (exported) symbols from another package, issue (use-package :another-package). Example on the REPL:
(asdf:load-system :ltk)
(use-package :ltk)
Sometimes one wants to use symbols that are not imported. You can then prefix them with the package, like bar:foo, where bar is the package name and foo the symbol.
When working on a real system, you will usually define one or more packages for it. This is done through defpackage, which you can tell what other packages to import directly:
(defpackage #:my-app
(:use :cl
:ltk))
Then, you need to switch to that package:
(in-package #:my-app)
When setting up a more complicated system with several interdependent files, a system definition facility becomes worthwhile. The currently most widely used is ASDF, although a handful of alternatives exist.
ASDF doesn't load a package into the COMMON-LISP-USER package. As a result, WITH-LTK isn't defined in your current package, so you need to do this:
(asdf:oos 'asdf:load-op :ltk)
(in-package :ltk)
;put your function here
Related
I have a very weird requirement that lexically binding a special variable of another package.
In file A.lisp
(defpackage A
(:use #:CL)
(:export #:a-test))
(in-package A)
(declaim (special *a-sp-v*))
(defun a-test (&key (v *a-sp-v*))
(print v))
in file B.lisp
(defpackage B
(:use #:CL #:A))
(in-package B)
(defun b-test ()
(let ((*a-sp-v* 1)) ; cannot let a-test know
(a-test)))
I keep receiving the error The variable A::*A-SP-V* is unbound. in my REPL.
Are there some methods I can bind *a-sp-v* in the package B? Let a-test function running with special *a-sp-v* no matter what package it is in?
Your code is fine (I would use defvar instead of declaim special though).
You can bind any symbol, it does not matter which package it resides in.
You just need to make sure you bind the symbol you need to bind and not something else.
E.g., since you are not exporting a::*a-sp-v* from a, your b-test binds b::*a-sp-v* rather than a::*a-sp-v*.
If you replace *a-sp-v* with a::*a-sp-v* in b-test, it should work.
Alternatively, you can add #:*a-sp-v* to the :export section in (defpackage A ...)
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 .
My following code snippets will give SB-INT:SIMPLE-READER-PACKAGE-ERROR;
I know it is because package "quicklisp-quickstart" is not defined yet while REPL reads the code; But the package IS defined in "quicklisp.lisp".
How can I make the following code work?
Or How can I tell the common lisp reader this package will be defined in the dynamically loaded file?
* (let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
(user-homedir-pathname))))
(if (probe-file quicklisp-init)
(load quicklisp-init)
(progn
(load "quicklisp.lisp")
(quicklisp-quickstart:install))))
debugger invoked on a SB-INT:SIMPLE-READER-PACKAGE-ERROR in thread
#<THREAD "main thread" RUNNING {100299C6A3}>:
Package QUICKLISP-QUICKSTART does not exist.
Stream: #<SYNONYM-STREAM :SYMBOL SB-SYS:*STDIN* {100017F893}>
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
You can use FIND-SYMBOL to try and find the function, and call it with FUNCALL. Something like
(let* ((package (find-package :quicklisp-quickstart))
(function (unless (null package)
(find-symbol (string '#:install)
package))))
(if (null function)
(error "Can't install...")
(funcall function)))
(solved, see the comments)
Recently I've been working on an API that has to interface with an already existing service. Everything seems to be working quite well, and my project is just starting to get large enough that I would see some benefit from throwing things into a package. As this is my first "real" project in CL, I think I'm not fully understanding the packaging/loading mechanisms going on here.
My basic problem is that I have a bunch of code that uses macros to generate functions/classes, interns them into my package, and then exports certain functions/accessors that people will eventually use to interact with the API. If I load the files individually like so:
(load "~/src/lisp/cl-bitcoin/bitcoin.lisp")
(load "~/src/lisp/cl-bitcoin/classes.lisp")
(load "~/src/lisp/cl-bitcoin/functions.lisp")
Everything works well. The functions declared by my macros are interned and exported correctly and I'm able to call them to interact with the API. However, if I attempt to do the following:
(ql:quickload :btc)
Quicklisp tells me that everything was loaded properly - and it seems that most of the loading process happened as I expected since all of my dependencies are loaded and available for use. The problem is that everything related to my package is not available. This includes functions that are exported directly from my package.lisp file. For reference, here are my .asd and package files:
package.lisp
(defpackage #:btc
(:use #:cl)
(:export #:set-connection-parameters
#:reset-rpc-id
#:with-connection-parameters
#:btc-base-err
#:btc-base-id))
btc.asd
(asdf:defsystem #:btc
:serial t
:depends-on (#:drakma
#:flexi-streams
#:cl-json)
:components ((:file "package")
(:file "bitcoin")
(:file "classes")
(:file "functions")))
I feel like I'm missing something fairly obvious here - I've been looking into eval-when and other related loading functions but haven't been able to figure this out. Can someone explain to me what's going on here?
Thanks for your help.
Edit: Here's what my REPL looks like:
; SLIME 2011-02-04
CL-USER> (ql:quickload :btc)
To load "btc":
Load 1 ASDF system:
btc
; Loading "btc"
..
(:BTC)
CL-USER> (btc:help "getinfo")
Invoking restart: Return to SLIME's top level.
; Evaluation aborted on #<SIMPLE-ERROR #x30200175DF0D>.
CL-USER> ; Reader error: No external symbol named "HELP" in package #<Package "BTC"> .
; No value
CL-USER> (load "/Users/jordan/src/lisp/cl-bitcoin/bitcoin.lisp")
#P"/Users/jordan/src/lisp/cl-bitcoin/bitcoin.lisp"
CL-USER> (load "/Users/jordan/src/lisp/cl-bitcoin/classes.lisp")
#P"/Users/jordan/src/lisp/cl-bitcoin/classes.lisp"
CL-USER> (load "/Users/jordan/src/lisp/cl-bitcoin/functions.lisp")
#P"/Users/jordan/src/lisp/cl-bitcoin/functions.lisp"
CL-USER> (btc:help "getinfo")
#<BTC::BTC-SINGLE #x3020017DBDDD>
CL-USER>
And the code to generate functions:
;;;; package information
(in-package #:btc)
;;; externally visible functions - this class contains the public api for
;;; cl-bitcoin as well as the function building framework that we need to
;;; easily handle the multiple return types that are possible from the
;;; bitcoind server methods
;; function building framework - resolving function return types into
;; specific btc objects (as defined in classes.lisp)
(defun create-btc-obj (fn result err id)
(case fn
((:getbalance :help) (make-btc-single result err id))
(otherwise (error "Unable to parse function ~S to a btc object" fn))))
(defmacro defbtcfun (name &rest args)
(let ((g (gensym)) (result (gensym)) (err (gensym)) (id (gensym)))
`(progn
(defun ,name ,args
(let ((,g (intern (string ',name) :keyword)))
(multiple-value-bind (,result ,err ,id) (get-bitcoind-result ,g ,#args)
(create-btc-obj ,g ,result ,err ,id))))
(export ',name 'btc))))
;; function definitions (each of these functions should have a corresponding case in
;; create-btc-obj above, otherwise a condition will be signaled
(defbtcfun help method)
(defbtcfun getbalance account minconf)
Jordan Kaye posted this as a comment, but never turned it into an answer:
It turns out that this was just an incorrect configuration issue in
asdf by me.. I accidentally set up the project in an incorrect
directory. When loading the project, quickload was actually loading an
entirely separate .asd file than the one that I was expecting. So,
when I loaded the (correct) files manually, the code worked as
expected - quickload was loading the wrong files. Thanks a lot for
your help, it led me to figure out the cause!
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.