Lets say i define a macro
(defmacro foo(x)
(print x))
Now i want to be able to always load this macro in all my lisp files in future where should i save this macro?
Every CL implementation has an init file it calls on start. For SBCL that is ~/.sbclrc. Usually also quicklisp has some setup code in there if you installed quicklisp.
So you could add a line:
(load #P"path/to/your/macro/file.lisp")
And it'll get loaded each time you start SBCL.
You want to have a library.
A library can contain any number of definitions, not only macros.
The de facto standard way to define systems (which is a more general term for libraries, frameworks, and applications — units of software) is to use ASDF.
Let's say that you put your macro into a lisp file:
;;;; my-util.lisp
(in-package cl-user)
(defpackage my-util
(:use cl))
(in-package my-util)
(defmacro foo (x)
`(whatever ,x etc))
Then you put that under a directory that is known to ASDF. One useful directory for that is ~/common-lisp/, so let's use ~/common-lisp/my-util/. In the same directory, put the system definition file:
;;;; my-util.asd
(in-package asdf-user)
(defsystem "my-util"
:components ((:file "my-util")))
Now you can load this utility into any lisp interaction, e. g. on the repl:
CL-USER> (asdf:load-system "my-util")
Or in a different system:
;;;; my-application.asd
(in-package asdf-user)
(defsystem "my-application"
:depends-on ("my-util")
...)
In the case of utility libraries, you often want to use their package so that you don't need to package-qualify the symbols.
If you want things that only work on your computer (like shortcuts for your REPL use or one-off scripts), you can sometimes get away with adding things to your implementation's init file.
Related
I've built a library that wraps custom C code and thinking about the best way to build the shared library as part of the ASDF load. The makefile is conditionalised for various OSs, so it could be as simple as uiop:run-program ..., but I thought I'd ask here if there were a more standard idiom for this.
Because the C code is specific to this application, it won't be available through a package manager and must be built specifically for each users machine. I'm fine with documenting a manual build, but if I can smooth things for the user I will. I notice that Python seems to have some kind of automated way of building libs for their CFFI and wonder if there's something for CL.
For an answer to my own question: there seems to be neither a de-facto way of doing this (based on a search of github asd files), nor a definitive method in the ASDF best practices, though there are some ideas to be gleaned from that document.
I'll put my implementation out as a suggested idiom for this use case, along with some possible alternatives. Hopefully some of the ASDF experts here will correct any misunderstandings.
;; Define a makefile as a type of source file for the system
(defclass makefile (source-file) ((type :initform "m")))
;; tell ASDF how to compile it
(defmethod perform ((o load-op) (c makefile)) t)
(defmethod perform ((o compile-op) (c makefile))
(let* ((lib-dir (system-relative-pathname "cephes" "scipy-cephes"))
(lib (make-pathname :directory `(:relative ,(namestring lib-dir))
:name "libmd"
:type #+unix "so" #+(or windows win32) "dll"))
(built (probe-file (namestring lib))))
(if built
(format *error-output* "Library ~S exists, skipping build" lib)
(format *error-output* "Building ~S~%" lib))
(unless built
(run-program (format nil "cd ~S && make" (namestring lib-dir)) :output t))))
(defsystem "cephes"
:description "Wrapper for the Cephes Mathematical Library"
:version (:read-file-form "version.sexp")
:license "MS-PL"
:depends-on ("cffi")
:serial t
:components ((:module "libmd"
:components ((:makefile "makefile")))
(:file "package")
(:file "init")
(:file "cephes")))
This works fine, on both MS Windows and UNIX. Adding a method to perform seems to be the most common method on github.
An alternative might be to use a build-op, as described in building a system. The description
Some systems offer operations that are neither loading in the current
image, nor testing. Whichever operation a system is meant to be used
with, you may use it with:
(asdf:make :foobar)
This will invoke build-op, which in turn will depend on the
build-operation for the system, if defined, or load-op if not.
Therefore, for usual Lisp systems that want you to load them, the
above will be equivalent to (asdf:load-system :foobar), but for other
Lisp systems, e.g. one that creates a shell command-line executable,
(asdf:make ...) will do the Right Thing™, whatever that Right Thing™
is.
suggest to me that this is rather close to the idea of building a C library, and it would map nicely to the mental model of using a makefile and the asdf:make command. I didn't find too many examples in the wild of this being used though and technically we are loading the C lib into the existing image.
Another point that could be reconsidered is the detection of an existing shared library to avoid the rebuild. make will avoid recompiling if the shared library exists, but will still call the linker again. This causes errors because it can't write to the shared library when it's in use, at least on MS Windows. The ASDF example used Lisp code to detect the existence of the library and avoiding recompilation, but an alternative might be to use output-files.
The ASDF docs are a bit muddled on the purpose of output-files and there are no examples that make their intentions clear, but in the manual section on creating new operations we have:
output-files If your perform method has any output, you must define a
method for this function. for ASDF to determine where the outputs of
performing operation lie.
which suggests that defining the shared library (libmd.so or libmd.dll) is the recommended way to avoid a recompilation if the output-files already exists.
Finally, the C library could be considered a secondary system, cephes/libmd in this case, and added to the :depends-on clause in the main system. The section on other secondary systems demonstrates building an executable this way, with build-op. Except for the fact that this is building an executable and hard-codes ".exe" it seems to map well onto the use case:
To build an executable, define a system as follows (in this case, it's
a secondary system, but it could also be a primary system). You will
be able to create an executable file foobar-command by evaluating
(asdf:make :foobar/executable):
(defsystem "foobar/executable"
:build-operation program-op
:build-pathname "foobar-command" ;; shell name
:entry-point "foobar::start-foobar" ;; thunk
:depends-on ("foobar")
:components ((:file "main")))
The build-pathname gives the name of the executable; a .exe type will
be automatically added on Windows.
I didn't use this method because the secondary system would look almost exactly like the primary one does now, but would be slightly less understandable.
Let's say we have the following prerequisites:
(quickproject:make-project "lib1")
(quickproject:make-project "lib2")
;;;; Modify lib1/package.lisp like that:
(defpackage #:lib1
(:use #:cl)
(:export #:symbol1))
;;;; Modify lib2/package.lisp like that:
(defpackage #:lib1
(:use #:cl)
(:export #:symbol2))
(quickproject:make-project "project1")
;;;; Edit the project1's asdf:defsystem so that it has the following dependencies:
:depends-on (:lib1 :lib2)
Load project1 and inspect the lib1 package and you will note that you have both symbol1 and symbol2 there.
Implications:
Different dependencies can pollute the packages of other dependencies
Worse - one dependency can redefine symbol definitions of another dependency and break the system.
I can probably solve my current problem by adopting a package naming convention like the one used in Java (with long delimited names). However, this appears to be a problem that is supposed to be solved as a community. We need a general purpose solution that will apply to all CL libraries. What would that be?
I want to create a source file in which most of the functions there defined, are local to that source file. It's the same purpose that would be served in C by marking the functions static; in C++ one could also surround them with namespace { ... }. I get the impression in Lisp, the package system is the appropriate tool. However, my attempts so far are not working.
This is what I currently have, but SBCL rejects it with the claim that global-fun is undefined. Explicitly referring to it as cl-user:global-fun, produces similar results. What should I be doing?
(defun global-fun ()
(format t "global~%"))
(defpackage :local-package
(:use :common-lisp)
(:use :cl-user))
(in-package :local-package)
(defun local-fun ()
(global-fun)
(format t "local~%"))
You're nearly there. You might use Slime's autocompletion to find out.
Either export global-fun, or access it with a double colon: (cl-user::global-fun).
With another global-package:
(defpackage :global-package
(:use :common-lisp) ;; <-- can be :cl
;; (:use :cl-user) <-- not necessary
(:export :global-fun))
(in-package :global-package)
(defun global-fun () …)
(defpackage :local-package
(:use :cl
:global-defun)) ;; <-- one ":use" is possible
(in-package :local-package)
; etc
There seem to be some misconceptions here.
There is no such thing as a “global function” in Common Lisp. The thing you defined first in your file, global-fun is in some package, most likely the cl-user package.
There is also no direct correspondence between packages and files. You can define things for different packages in a single file, and you can define things for a single package in multiple files. To make things unambiguous and easy to read, there is a very sensible convention to always start a source file with an in-package form (in some styles preceded by a defpackage form), and to never put another in-package somewhere later in the file.
When you write a symbol without package, e. g. somefun or myarray, it is interned (i. e. a sort of idempotent registration) into the current package (see below what that is). This is independent from whether you currently define something or refer to it, because it is done by the reader when reading your source code forms. In both of the following forms, the symbol named foo is interned into the current package (and both result in the identical symbol to be used):
(defun foo ()
…)
(foo)
In order to refer to a symbol from a different package, you need to put the package name as a prefix with :: as separator, as in my-package::foo, but this is usually a code smell because…
… you should export any symbols that a user of your package is intended to use, from your package definition:
(defpackage my-package
(:use common-lisp)
(:export foo))
You can refer to exported symbols from another package with a single colon as separator, as in my-package:foo, and this is good style.
Now, the current package is just the value of the variable *package*. If you look at it from the point of view of a REPL session, this is the argument of the most recent in-package call. In the context of whole file compilation, it is the value of the lexically closest preceding in-package form. In the context of single-form compilation in a file, the IDE will (in any case I have seen) look for that preceding in-package form even if it is not evaluated explicitly. In a pristine Lisp image, the starting package is common-lisp-user, which has a nickname cl-user.
My lisp file contains about 50 function and macro definitions. At the head of the file is:
(defpackage :utils
(:use :common-lisp))
(in-package :utils)
; ... ~50 defuns/defmacros follow along with some other code
I want to export all these 50 definitions. But no other symbols.
To write them all out in :export clauses inside defpackage seems very tedious.
I tried getting the necessary symbols by using loop's facility for listing symbols in a package. But both "symbol" and "present-symbol" don't output the needed definition symbols. I could somehow subtract "external-symbols" and inherited symbols. But this seems like the kind of thing everyone would need and there should be an established easy solution. I looked around and haven't found a straightforward answer.
How do I export all the definition symbols without having to write them out individually and manually?
scan symbols
You can scan all symbols and export all that have a function binding (this includes macro names):
(defun export-fbound-symbols (package)
"export symbols with function bindings"
(do-symbols (s package)
(when (fboundp s)
(export s package))))
This is usually not a very good idea: good software engineering practice is to limit the set of public interfaces.
be more selective
You can redefine defun and defmacro so that they automatically export their definienda.
See exporting.lisp in CLISP. E.g.,
(defmacro define-function (name lambda-list &body body)
`(progn
(export ',name)
(defun ,name ,lambda-list ,#body)))
Note that this ignores the possibility of (defun (setf foo) (...) ...).
No, this is not something everyone needs. Usually, you'd export them as you write (and actually need) them.
I'd probably use an ad hoc keyboard macro for this. You could also write a little Lisp function to read your file form by form and output the relevant symbols for copy-paste.
All I wanted was to load an initialisation file for swank which wouldn't affect my lisp when it's started without swank...
I first tried #+swank (defun...) in my file that's loaded from ccl-init (trying this on ccl 1.10 + windows), and soon realised it's sourced before swank is loaded (obviously).
My aim is to define a simple function in :cl-user everytime I start swank. I just ended up with a swank add-hook to load my init.lisp file, and since I want to define the function in cl-user, I tried this in the init.lisp:
(let ((current-package *package*))
(in-package :cl-user)
(defun cd (dir)
(swank:set-default-directory
(parse-namestring dir)))
(in-package current-package))
Now, I don't recall if a defun in let was allowed, but lisp doesn't complain for it, but rather tells me that cur-pck symbol doesn't exist, and it seems when we switch the package, cur-pck binding gets out of scope. I thought cur-pck is a lexical binding, and that it should be reachable from within the lexical region, being independent from a package, am I wrong?
Why do I switch packages? I'm thinking that loading this file from swank at some initialisation point will define things in some swank package, that's why I wanted to try switching to cl-user first, define the function symbol, and switch back to let swank do it's thing.
At this point I guess I need someone to tell me I'm approaching the problem from the wrong angle, and that I should better choose an easier solution.
Additionally, out of curiosity in case above is the complete wrong approach, is there a way to define a symbol in another package within a function or a closure?
Switching packages in a form has no direct effect on the form
Let's look at this:
(in-package "FOO")
(let ((x 10))
(in-package "BAR")
(setf x 20))
Which x does it set to 20? FOO::X or BAR::X?
Well, it is FOO::X. Switching packages during execution has no effect on the symbols already read. The whole let form is read at once and the *package* value is used for that. Having an IN-PACKAGE in the form itself has no effect on the form itself.
Symbol with a package prefix
If you want to use a symbol in a certain package, just write the package prefix:
cl-user:foo ; if FOO is exported and the package exists
or
cl-user::foo ; if foo is not exported and the package exists
for example:
(defun cl-user::cd (...) ...)
Computing with symbols
You can also compute new symbols in packages you don't know yet:
(let ((sym-name "A-NEW-SYMBOL")
(my-package-name "SOME-EXISTING-PACKAGE"))
(intern sym-name my-package-name))
If the package does not exist, you can create it.
You can also set the function of a computed symbol:
(setf (symbol-function (compute-a-function-symbol))
#'(lambda ()
'foo))
If you want to define a function in a different package that the current one you can use a qualified symbol for a name
(defun cl-user::cd (dir)
(swank:set-default-directory
(parse-namestring dir)))
The binding is not being "lost". To test so yourself add (princ cur-pck) before the in-package form.
If you try evaluating (in-package *package*) you will see why your code fails to switch packages. The in-package macro does not evaluate its argument. The code that would give us the code we would want to evaluate is:
(let ((cur-pck *package*))
(in-package :cl-user)
(defun cd (dir)
(swank:set-default-directory
(1+ 2)))
(princ cur-pck)
`(in-package ,cur-pck))
However, as Rainer Joswig noted in his answer the in-package has no effect on forms already read, so it wouldn't work as desired even as a macro.
A style nitpick, don't use abbreviations, write current-package.
IN-PACKAGE is a macro, not a function. The problem in your code is that saying (in-package cur-pck) tries not to switch into the package denoted by the cur-pck variable but to the package named CUR-PCK (which obviously does not exist).
You can set the package temporarily with
(let ((*package* (find-package :cl-user)))
(defun cd (dir)
...))
But then again, the easiest way to achieve what you are doing would be
(defun cl-user::cd (dir)
...)
which totally eliminates the need to set the current package.