How to make and use library with lisp (clisp)? - lisp

In C/C++, I can make a library, and make it static one or dll using #include "" in source code, and -labc when linking.
How do I have the same feature in lisp?
As an example of util.lisp in directory A. I define a library function hello.
(defpackage "UTIL"
(:use "COMMON-LISP")
(:nicknames "UT")
(:export "HELLO"))
(in-package util)
(defun hello ()
(format t "hello, world"))
And try to use this library function from main function.
(defun main ()
(ut:hello))
(main)
I tried
clisp main.lisp A/util.lisp
But, I got the following message
*** - READ from #: there is no package with name "UT"
What's the equivalent of #include "" to use the library?
What's the equivalent of -lutil to load the library? What's the command line for clisp/sbcl to use the library?
And for defpackage, Is this equivalent to namespace?
ADDED
I just had to load the library.
(load "./A/util.lisp")
(defun main ()
(ut:hello))
(main)
And run 'clisp main.lisp' works fine.

What you are looking for are called systems. Common Lisp's defpackage has nothing to do with this, and yes, it's about namespaces. Have a look at the HyperSpec, or the idiot's guide (see Xach's comment below) to read more about it.
You can restrict yourself to merely loading files, but usually, a system definition facility is used; mostly ASDF nowadays. A minimal example:
(defsystem my-system
:name "my-system"
:version "0.0.1"
:author "myself"
:license "LLGPL"
:description "it's a system."
:serial t
:components ((:file "packages")
(:file "stuff")
(:file "more_stuff")))
Where packages.lisp would contain the package definition, stuff and more_stuff are the lisp or fasl files to be loaded. This system definition (usually named filename.asd) must be symlinked to (or located in) a directory contained in asdf:*central-registry* for ASDF to find your system. Then, you can load the system thusly:
(asdf:oos 'asdf:load-op 'my-system)
An alternative to this has been added in more recent versions of ASDF:
(asdf:load-system 'my-system)
Or, when using slime, by pressing ,l my-system RET.

You have to load util.lisp before main.lisp:
> (load "util.lisp")
> (load "main.lisp")
> (main)
hello, world
NIL
Practical Common Lisp has a good introduction to defining and using packages.

Common Lisp is an image base language, although usually to a lesser extent than Smalltalk. This means that you use a library by loading it into the image, using LOAD (if used explicitly the often in form (load (compile-file "your-file-here"))), or usually with a system definition facility like ASDF. The loaded code is then available for all code compiled/loaded in the future.
Packages are indeed namespaces. They deal with mapping strings to symbols only, they are not connected directly to files or functions or anything else. You received a package error because you attempted to load a file using a package before a file defining it.

Related

Multiple Emacs Lisp config files lead to "free variable" and "function not known to be defined" warnings

I've been looking for emacs config files for a while, so that I learn how to structure my Emacs config in the most optimal way. Now i'm looking at purcell's config files which look very tidy and simple to read.
However, for every config file I've found there's always the same problem: "free variable"
and "function not known to be defined" warnings on all the included files. It is quite frustrating to see all the red underlines from flymake everytime, and it also makes me question if this really is the best way to write the config file.
Here's a file from the repository mentioned above:
;;; init-python.el --- Python editing -*- lexical-binding: t -*-
(setq auto-mode-alist
(append '(("SConstruct\\'" . python-mode)
("SConscript\\'" . python-mode))
auto-mode-alist))
;;WARNING: assignment to free variable ‘python-shell-interpreter’
(setq python-shell-interpreter "python3")
(require-package 'pip-requirements)
(when (maybe-require-package 'toml-mode)
(add-to-list 'auto-mode-alist '("poetry\\.lock\\'" . toml-mode)))
;;WARNING: reference to free variable ‘black’
(when (maybe-require-package 'reformatter)
(reformatter-define black :program "black" :args '("-")))
(provide 'init-python)
;;WARNING: the following functions are not known to be defined: require-package, maybe-require-package, reformatter-define
;;; init-python.el ends here
The python-shell-interpreter is a variable defined from the python-mode package.
The require-package and maybe-require-package are defined in a custom local file called init-elpa.el which is requires'd by the init.el file and thus they're not directly recognized by this file.
The black variable warning is the mostr "intricate": I guess it's caused by the fact that the reformatter package isn't included because maybe-require-package isn't included as well.
This gives me a headache. If I see it correctly, the root problem is the fact that the included files (init-python.el et al.) depend on stuff from the including file (init.el) without it being explicitly stated.
Is there a better way to structure an Emacs Lisp config among multiple files?
The python-shell-interpreter is a variable defined from the python-mode package.
Add (require 'python-mode) to the top of the file (or simply above the code which depends on that).
The require-package and maybe-require-package are defined in a custom local file called init-elpa.el
Add (require 'init-elpa) to the file (I'm assuming it provides the init-elpa feature).
which is require'd by the init.el file
This is fine -- require does nothing if the library in question has already been loaded. Even when there's an overarching init file loading other files, it's sensible for each file to require the things it needs (unless there are circular dependencies).
The black variable warning is the most "intricate": I guess it's caused by the fact that the reformatter package isn't included because maybe-require-package isn't included as well.
I'm guessing that reformatter-define is a macro and that the symbol black is not actually used as a variable. When only macros are required, one would typically (eval-when-compile (require 'reformatter)) but judging by the name maybe-require-package it's intended that reformatter might not be loadable at all. If that's all accurate, you can use this wrapper to cope with the false-positive:
(with-suppressed-warnings ((free-vars black))
...)
See C-hig (elisp)Compiler Errors for further information on handling byte-compilation warnings and errors.

Common Lisp: How to get (in-package ...) to work from within Emacs Slime

64-bit Windows 7
Clozure Common Lisp Version 1.9 WindowsX8632
Emacs 24.3.1
Slime changelog date 2014-06-17
I have an example .lisp file which starts out as follows:
(ql:quickload 'qt)
(in-package "QT")
The rest of the program shows a dialog box.
When I run this from the command line, wx86cl -load helloqt.lisp it seems to work fine.
When I run this from Emacs Slime (C-x C-k) it says there is no package "QT".
However if I first evaluate the first line individually (C-x C-e) then I can compile the whole thing and it works, modulo the normal issues of trying to run a QT thread from within Slime on Windows.
How do I make it so I can compile/run the file from emacs without having to manually evaluate the first line first?
Also, why doesn't (in-package ...) change the current package in the Slime session? I have to change it manually if I want to interact with the package contents.
When you compile the file as a whole, it is first read as a whole. At that time, none of it has yet been evaluated, so the package QT is not defined yet.
You can either use eval-when to evaluate something at an earlier time, or use a system definition facility (ASDF is predominant nowadays) to load your system in the right order.
Eval-when:
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload '#:qt))
(in-package #:qt)
Note that you usually should not muck around in library packages but define your own, fresh package to hold your code:
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload '#:qt))
(defpackage #:qt-example
(:use #:qt))
(in-package #:qt-example)
;; your code here
(In case you are wondering, defpackage, defun, defclass etc. are specially designed macros that expand to a form inside such an eval-when.)
This is sometimes OK for little one-off scripts. For systems of any noteworthy size, especially as soon as they have more than one source file, use ASDF:
;;;; qt-example.asd
(in-package #:cl-user)
(asdf:defsystem #:qt-experiments
:description "Some experiments with QT."
:serial t
:components ((:file "package")
(:file "qt-example"))
:depends-on (#:qt))
;;;; package.lisp
(defpackage #:qt-example
(:use #:qt))
;;;; qt-example.lisp
(in-package #:qt-example)
ASDF comes with most open-source Common Lisp implementations. You might need to set up the ASDF registry. I like to have one or two base directories for all my local projects, so that I can just put the following into ~/.config/common-lisp/source-registry.conf:
(:source-registry
(:tree (:home "devel"))
(:tree (:home "src"))
:inherit-configuration)
Then ASDF finds all systems defined below those directories. In SLIME, you can just use ,load-system or ,open-system from the REPL with the system name to load it, resp. open all files in it, optionally loading it.
When compiling a single toplevel form (using C-c C-c) from a file, SLIME looks backward from there for an in-package form to find out what package it should assume. Conventionally, you should only have a single in-package form per file, at its top.
A commonly useful shortcut is C-c ~ in Lisp source files, which switches the REPL to the directory of the file and the effective package at point.
A little hard to find, but there is slime-repl-set-package:
(defun slime-connected-hook-switch-to-stumpwm-package ()
(slime-repl-set-package "STUMPWM"))
(add-hook #'slime-editing-mode-hook
#'slime-connected-hook-switch-to-stumpwm-package)

load a module without evaluating its body at top level

I have this file:
#lang racket
(provide install global-var)
(define global-var 'test)
(define (install)
(set! global-var '(aaa)))
(install)
And I start the repl, typing so:
Welcome to Racket v5.3.5.
> (define global-var "test007")
> global-var
"test007"
> (require "test.rkt")
'(install)
> global-var
'test
Is it possible to load only some definitions from the file test.rkt, such that the loading does not change the value of global-var, only if I call myself (install), after I load?
I want to use only the standard racket system, not outside packages that are not installed by default in racket.
The short answer is: probably not. You should think of a racket module as a pre-compiled bundle of code that exports certain functions. Any expressions at the top level (such as the call to 'install' here) are conceptually part of the module's setup; allowing a user to use the definitions without running the setup code would invalidate the assumptions of the module writer---not nice for the writer of the module.
To take an example, I have a sound library; requiring the sound library module initializes the sound playback. If there were a tricky way to load the module without running this code, my invariants would be violated.
Perhaps you can explain why it's inconvenient for you to edit the source code?

SLIME and Quicklisp not playing nice with each other

I'm using Emacs as my Common Lisp (SBCL, to be exact) editor, with SLIME. I set up Quicklisp as per the instructions here, and checked if it worked outside of SLIME, and everything was fine - I could grab and download code, include it, everything.
Now, I was trying to use the Compile/Load File command in Emacs for a source file with the following at the top:
(ql:quickload "priority-queue")
(defpackage :tournament
(:use :cl :priority-queue))
(in-package :tournament)
Now, once again, not in SLIME, this worked fine. However, in SLIME, I get an error of the following form:
The name "PRIORITY-QUEUE" does not designate any package.
[Condition of type SB-KERNEL:SIMPLE-PACKAGE-ERROR]
Plus a backtrace, of course. Am I missing something in particular? I installed slime using package-install from Emacs, and I have the following code in my .emacs file to set it up:
(setq inferior-lisp-program "/usr/local/bin/sbcl")
(require 'slime)
(slime-setup)
This is happening because of the separate times of compilation and loading.
When compiling, plain function calls (like ql:quickload) are not evaluated. When the compiler tries to process the defpackage form (which is not a plain function call, but a macro that has side-effects at compile-time), the function that loads "priority-queue" has not been called and the package is not available.
You won't see this if you load the file instead of compiling and loading, because load evaluates each form as it loads.
There are a few options available. The simplest is to wrap your call to ql:quickload in eval-when, e.g.
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload "priority-queue"))
I prefer to define a system for my projects, however small, so I would make a tournament.asd file that looks like this:
(asdf:defsystem #:tournament
:depends-on (#:priority-queue)
:serial t
:components ((:file "tournament.lisp")))
I'd put that in ~/quicklisp/local-projects/tournament/ (along with tournament.lisp) and use (ql:quickload "tournament") in the repl to get started and load it.
I use that latter setup so often that I wrote a Lisp program to do it for me called quickproject.

Call function in another lisp file

I have to write a game in Lisp. In order to make it clear, I wanted to split the code in different .lisp files.
How can I call a function out of a function in the other file?
E.g. file1.lisp has a function called function1 and file2.lisp has a function called function2.
How can I call function2 out of function1?
Thanks!
Just so you know, there are a variety of different Lisp systems. I'll post the answer for Common Lisp.
The naive way is to use (load "filename.lisp"), but that doesn't really work very well after a while. Therefore...
Common Lisp has a library called "ASDF", which handles packaging and file management. There's a bit of setup to ASDF.
Create directory where ASDF looks for files.
Add this information to my Lisp system's init file.
I use this in my .sbclrc file (assuming that I created a .asdf file in ~) :
(pushnew "~/.asdf/" asdf:*central-registry* :test #'equal)
I usually use a previously built ASDF file and then modify it.
Here's a sample ASDF file's contents:
(asdf:defsystem #:cl-linq
:depends-on ( #:alexandria #:anaphora)
:components ((:file "cl-linq"))
:name "cl-linq"
:version "0.1"
:maintainer "Paul Nathan"
:author "Paul Nathan"
:licence "LLGPL"
:description "CL LINQ style interface with strains of SQL"
:long-description
"DSL for managing and querying datasets in a SQL/LINQ style
syntax. cl-linq provides a simple and usable set of primitives to
make data examination straightforward. ")
I put this code in a file cl-linq.asd next to my source code (cl-linq.lisp from the component "cl-linq" in the defsystem) and then symlink the cl-linq.asd file to my ~/.asdf/ directory.
Within my cl-linq.lisp file I include this:
(defpackage :cl-linq
(:use
:common-lisp
:anaphora)
(:export
#:query
#:cl-linq-select))
(in-package :cl-linq)
So for your case, I would have 2 components; each with their own defpackage form, exporting the functions out that the other package needed.
For the examples, I've taken the code from CL-LINQ, a project of mine. You are quite free to use it as a template.
This is for Emacs Lisp (aka elisp)
Create a file at this location: ~/.emacs.d/init.el
Create a file at this location: ~/.emacs.d/file1.el
Create a file at this location: ~/.emacs.d/file2.el
Now, open up ~/.emacs.d/init.el and write (and then save):
(load "~/.emacs.d/file1.el")
(load "~/.emacs.d/file2.el")
(defun run-both-functions ()
(interactive)
(switch-to-buffer "*Messages*")
(first-function)
(sit-for 2)
(second-function))
Now, open up ~/.emacs.d/file1.el and write (and then save):
(defun first-function ()
(message "My name is Fred."))
Now, open up ~/.emacs.d/file2.el and write (and then save):
(defun second-function ()
(message "My name is George."))
Now, restart Emacs and type: M-x run-both-functions RET
Any functions that you put into any of the three (3) files mentioned above will be accessible to other functions. You will note that run-both-functions includes an (interactive) statement, which means that the user can call the function with M-x or a keyboard shortcut.
If you use the function load it can be useful to not specify the file type.
Loading files: fasl or source
Instead of (load "foo.lisp") one can call (load "foo"). Typically Common Lisp provides the feature of compiling Lisp files to fasl (fast load) files. Those are usually pre-compiled byte code or native code. Typically the Common Lisp implementation will load the compiled code if a file exists for it. This saves time (because compiled code usually can be loaded much faster than Lisp source code) and the code usually is faster (because a file compiler has compiled it).
Often one uses a function to load the compiled file if it is newer, or first compile the source file to a new compiled file.
Loading a file, based on the current file being loaded
In (load "foo") the file foo is not a complete filename. For example we don't know the directory where it is loaded from. This depends on things like the value of *default-pathname-defaults* or in some implementations on a current directory (typical for Unix systems). It may be useful to load the file based on the file we are currently loading - if loading one file triggers more files to be loaded. For this Common Lisp has the variables *load-pathname* and *load-truename* (which is the real filename as used with the filesystem).
To load a file foo in the same directory as the currently loaded file call:
(load (merge-pathnames "foo" *load-pathname*))
To load a file foo in a subdirectory bar of the same directory as the currently loaded file call:
(load (merge-pathnames "bar/foo" *load-pathname*))
With Common Lisp I done it like this:
In file1.lisp I define a function sayHello and export that function under the package name helloLisp
(defpackage :helloLisp
(:use :common-lisp)
(:export #:sayHello))
(in-package :helloLisp)
(defun sayHello () (print "Hello!"))
In the file file2.lisp I require this file like that:
(require "helloLisp" "./file1.lisp")
(helloLisp:sayHello)
Tested with SBCL 1.4.11