I would like to know, what is the common approach to common-lisp interactive development in emacs (i use sly, but i think the slime instructions should be the same)
say i have this file:
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload :closer-mop))
(in-package :cl-user)
(defpackage :shapes
(:use :closer-common-lisp-user)
(:export #:rectangle))
(in-package :shapes)
(defclass rectangle ()
((height :initform 0.0 :initarg :height)
(width :initform 0.0 :initarg :width)))
which is quite simple.
Evaluating it experssion by expression seems to be ok, while loading the whole file (C-c C-l) gives me the following error:
The variable SHAPES:RECTANGLE is unbound.
[Condition of type UNBOUND-VARIABLE]
stripping it down to
(in-package :cl-user)
(defpackage #:shapes
(:use #:cl-user)
(:export #:rectangle))
(in-package #:shapes)
(defclass rectangle ()
((height :initform 0.0 :initarg :height)
(width :initform 0.0 :initarg :width)))
doesn't make any change.
compile-and-load (C-c C-k) doesn't work either, leaving me with:
; in: DEFCLASS RECTANGLE
; (SHAPES::DEFCLASS SHAPES:RECTANGLE NIL
; ((SHAPES::HEIGHT :INITFORM 0.0 :INITARG :HEIGHT)
; (SHAPES::WIDTH :INITFORM 0.0 :INITARG :WIDTH)))
;
; caught COMMON-LISP:STYLE-WARNING:
; undefined function: SHAPES::DEFCLASS
i see that defclass can't be properly resolved to from cl-user:defclass, but can't see the way to fix it.
I wonder what am i missing?
And what is the common flow for developing interactively in emacs?
The underlying problem here is that you are confusing two ways that packages can be used in CL. A package generally serves one, or both, of two purposes:
it can export a number of symbols, providing some kind of interface to functionality;
it can be a package in which other packages are used or from which symbols are imported, but which does not export any symbols (unless it is also a type 1 package).
There is no formal distinction between these types of packages, but there very often is an informal distinction. Packages which are of the second type above are often called *-USER with the canonical example being the CL-USER package. They often (but not always) serve as places for scratch work.
So what you are doing is defining a package whose use list is such a user package. You can see that this is not going to work by simply looking at the external symbols of this package. From your second example:
> (do-external-symbols (s (find-package "CL-USER"))
(print s))
nil
In other words, CL-USER exports no symbols at all. This means that your SHAPES package will initially not have access to any symbols at all, and in particular none of the CL symbols will be present.
Well, the language defines a canonical 'type 1' package, which is CL: the whole purpose of this package is to export the symbols which define the Common Lisp language, and only those symbols. So the definition of the SHAPES packages in your second example should be
(defpackage #:shapes
(:use #:cl)
(:export #:rectangle))
(Note that SHAPES is a type 1 package: it is providing some functionality in the form of SHAPES:RECTANGLE, and presumably is therefore intended to be used by other packages.)
Closer to MOP provides two packages which mirror the standard CL and CL-USER packages:
CLOSER-COMMON-LISP is like CL except that various symbols are replaced by ones defined by Closer to MOP, and there may be additional MOP symbols;
CLOSER-COMMON-LISP-USER is like CL-USER: it's a package intended general use, which users CLOSER-COMMON-LISP but which does not export any symbol at all.
Related
In most of the examples on the Internet, symbol equality is straight-forward:
(eq 'sym 'sym)
t
In my program, I want to compare symbols in a custom package:
(defpackage #:my-package
(:use #:common-lisp)
(:export #:my-function))
(in-package #:my-package)
(defun my-function (value)
(cond
((eq value 'sym)
(format t "SYM: YES~%"))
(t
(format t "SYM: NO~%"))))
(in-package #:common-lisp)
(my-package:my-function 'sym)
But when this code is executed, it displays:
SYM: NO
It seems like the 2 symbols are different:
(eq 'sym 'my-package::sym)
nil
The reason seems easy to understand, a symbol interned in a given package is not equal to a symbol with the same name interned in another package. Fair enough! But what is the idiom to compare 2 symbols, regardless the package?
Should we convert it to a string in a first place and compare strings?
(defpackage #:my-package
(:use #:common-lisp)
(:export #:my-function))
(in-package #:my-package)
(defun my-function (value)
(cond
((string= (symbol-name value) "SYM")
(format t "SYM: YES~%"))
(t
(format t "SYM: NO~%"))))
(in-package #:common-lisp)
(my-package:my-function 'sym)
The result is better, but there is an obvious issue regarding the character case.
How to check that 2 symbols are the same regardless their package?
The usual idiom is string=, which compares the names of symbols without regard to identity.
For example:
(eq 'x:a 'y:a) => nil
(string= 'x:a 'y:a) => t
I think you are confused about what 'being the same symbol' means.
Two symbols are the same symbol iff they are eq, which means that if they are not eq they are not the same symbol. In particular if two symbols have home packages which are different (again: not eq) they are not the same symbol.
If you want to know if two symbols have the same name then simply compare their symbol-names, as strings. But two symbols which merely have the same name are not necessarily the same symbol (for instance (eq '#:foo '#:foo) is false).
There are cases where it is useful to know whether two symbols have the same name (for instance the loop macro must do this so that (loop for ...) and (loop :for ...) mean the same thing) but these cases are fairly rare.
If what you want to do is know if two symbols have the same names you quite likely should be using strings instead.
If what you actually want to know is whether two symbols accessed from different packages are really the same symbol (so (eq 'x:foo 'y:foo), say) then eq is the appropriate test, and understanding the package system also helps.
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 ...)
The function find-data-from-command works fine when I run it without first doing the 'quickload' of the package. If I load the package it gives the error that split-sequence is undefined.
I have tried to reload split-sequence after loading the custom package. Doesn't work
(ql:quickload :<a-custom-package>)
(defun find-data-from-command (x desired-command)
(setq desired-data ())
(loop for line = (read-line x nil)
while (and line (not desired-data)) do
(progn
(setq commands (first (split-sequence ":" line)))
(setq data (split-sequence "," (first (rest (split-sequence ":" line)))))
(print (cons "command:" commands))
(cond
((equal commands desired-command) (return-from find-data-from-command data))))))
FIND-DATA-FROM-COMMAND
SIGMA 24 >
(setq obj-type (find-data-from-command (open "log.txt") "types"))
Error: Undefined operator SPLIT-SEQUENCE in form (SPLIT-SEQUENCE ":" LINE).
The problem is nothing to do with Quicklisp, it's to do with a package you've defined somewhere called SIGMA. In particular somewhere in your code is a form which looks like:
(defpackage "SIGMA" ;or :sigma or :SIGMA or #:sigma or ...
...
(:use ...)
...)
And then later
(in-package "SIGMA")
And the problem with this is that your package definition has an explicit (:use ...) clause.
defpackage, and the underlying function make-package has slightly interesting behaviour for the :use clause (or keyword argument in the case of make-package):
if none is given then there is an implementation-defined default;
if one is given then it overrides the default.
The idea, I think, is that implementations may want to provide a bunch of additional functionality which is available by default, and this functionality can't be in the CL package since the contents of that package is defined in the standard. So if you just say
(defpackage "FOO")
Then the implementation is allowed (and, perhaps, encouraged), to make the use-list of FOO have some useful packages in it. These packages might be the same ones that are in the default use-list of CL-USER, but I'm not sure that's required: the whole thing is somewhat under-specified.
The end result of this is that if you want to define packages which both make use of implementation-defined functionality and have explicit use-lists you have to resort to some slight trickery. How you do this is slightly up to you, but since you are by definition writing implementation-dependent code where you are defining packages like this, you probably want to make it clear that what you are doing is implementation-dependent, by some form like
(defpackage :foo
(:use ...)
#+LispWorks
(:use :lispworks :harlequin-common-lisp :cl)
...)
Or, if you just want some particular set of symbols
(defpackage :foo
(:use ...)
#+LispWorks
(:import-from :lispworks #:split-sequence))
Note that this is not quite the same thing as using a package containing the symbol.
In all these cases if your code has pretensions to be portable then there should be appropriate clauses for other implementations and a way of knowing when you're trying to run on an implemention you haven't yet seen: how to do this is outwith the scope of this answer I think.
Solved it.
The quickloading of the custom package was taking me into the package. I did not realize that. So I had to specify split-sequence is from outside. So, I replaced all occurrences of split-sequence in the function definition with
LISPWORKS:split-sequence
Then it worked.
If any one has a better solution, please do let me know. Thanks
(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!
Is there a way to temporarily import a few functions from a package into the current package, using standard common-lisp functions/macros?
I couldn't find one and had to roll my own. I'd rather not have to code anything up, or introduce another language construct, if the standard already provides such functionality.
(defmacro with-functions (functions the-package &body body)
"Allows functions in the-package to be visible only for body.
Does this by creating local lexical function bindings that redirect calls
to functions defined in the-package"
`(labels
,(mapcar (lambda (x) `(,x (&rest args)
(apply (find-symbol ,(format nil "~:#(~a~)" x)
,the-package)
args)))
functions)
,#body))
Example usage:
(defclass-default test-class ()
((a 5 "doc" )
(b 4 "doc")))
#<STANDARD-CLASS TEST-CLASS>
CL-USER>
(with-functions (class-direct-slots slot-definition-name) 'sb-mop
(with-functions (slot-definition-initform) 'sb-mop
(slot-definition-initform
(car (class-direct-slots (find-class 'test-class))))))
5
CL-USER>
EDIT: Incorporated some of Rainer's suggestions to the macro.
I decided to keep the run-time lookup capability, at the time cost of the run-time lookup to find the function in the package.
I tried to write a with-import macro that used shadowing-import and unintern, but I couldn't get it to work. I had issues with the reader saying that the imported functions didn't exist yet (at read time) before the code that imported the functions was evaluated.
I think getting it to work with shadowing-import and unintern is a better way to go, as this would be much cleaner, faster (no run-time lookup capability though) and work with functions and symbols in packages.
I would be very interested to see if someone can code up a with-import macro using unintern and shadowing-import.
It makes runtime function calls much more costly: it conses an arg list, looks up a symbol in a package, calls a function through the symbol's function cell.
It only works through symbols, not lexical functions. That makes it less useful in cases, where code is generated via macros.
Its naming is confusing. 'import' is a package operation and packages deal only with symbols, not functions. You can't import a function in a package, only a symbol.
(labels ((foo () 'bar))
(foo))
The lexical function name FOO is only in the source code a symbol. There is no way to access the function through its source symbol later (for example by using (symbol-function 'foo)). If a compiler will compile above code, it does not need to keep the symbol - it is not needed other than for debugging purposes. Your call to APPLY will fail to find any function created by LABELS or FLET.
Your macro does not import a symbol, it creates a local lexical function binding.
For slightly similar macros see CL:WITH-SLOTS and CL:WITH-ACCESSORS. Those don't support runtime lookup, but allow efficient compilation.
Your macro does not nest like this (here using "CLOS" as a package, just like your "SB-MOP"):
(defpackage "P1" (:use "CL"))
(defpackage "P2" (:use "CL"))
(with-import (p1::class-direct-slots) 'CLOS
(with-import (p2::class-direct-slots) 'P1
(p2::class-direct-slots (find-class 'test-class))))
The generated code is:
(LABELS ((P1::CLASS-DIRECT-SLOTS (&REST ARGS)
(APPLY (FIND-SYMBOL "CLASS-DIRECT-SLOTS" 'CLOS) ARGS)))
(LABELS ((P2::CLASS-DIRECT-SLOTS (&REST ARGS)
(APPLY (FIND-SYMBOL "CLASS-DIRECT-SLOTS" 'P1) ARGS)))
(P2::CLASS-DIRECT-SLOTS (FIND-CLASS 'TEST-CLASS))))
You can use import with a list of qualified symbols (i.e. package:symbol or package::symbol) you want to import and then unintern them.