Reading — step 1 of 5
Learn
Common Lisp's namespace system is packages. Each symbol belongs to a package; you import or qualify to access symbols from other packages.
Defining a package
(defpackage :my-app
(:use :common-lisp)
(:export #:greet #:farewell))
(in-package :my-app)
(defun greet (name)
(format nil "Hello, ~a!" name))
(defun farewell (name)
(format nil "Bye, ~a!" name))
(defun helper () ; not exported — package-private
"internal stuff")
:use :common-lispimports every symbol from the standard package — getdefun,format,let, etc.:exportlists what's PUBLIC. Symbols not exported are accessible only from inside the package.
Accessing symbols
From outside :my-app:
(my-app:greet "Ada") ; one colon — exported
(my-app::helper) ; two colons — internal (don't do this)
Importing
(defpackage :my-other
(:use :common-lisp :my-app)) ; pull in all of my-app's exports
(in-package :my-other)
(greet "Bob") ; works directly — was imported
Or selectively:
(defpackage :my-other
(:use :common-lisp)
(:import-from :my-app #:greet))
In-package
A file usually starts with:
(in-package :my-app)
After that, all definitions go in that package. Without it, definitions land in :cl-user (the REPL package).
Common pitfalls
Symbol equality across packages:
(eq 'foo 'my-app::foo) ; nil if 'foo is in cl-user, not my-app
A symbol's identity is its package + name. my-app::foo and cl-user::foo are different symbols.
Read-time package: when you read 'foo at the REPL, it goes into the current package (the one set by in-package). Files set their package; the REPL's package is :cl-user by default.
Standard packages
:common-lisp(alias:cl) — language built-ins:common-lisp-user(:cl-user) — REPL default:keyword— where keywords (:foo) live
Quicklisp packages
Real Common Lisp projects use Quicklisp (the package manager) and ASDF (the build tool):
(ql:quickload :alexandria) ; download + load
(alexandria:hash-table-keys table)
Typical project layout:
my-app/
my-app.asd ; ASDF system definition
package.lisp ; defpackage forms
src/
core.lisp
utils.lisp
my-app.asd:
(defsystem :my-app
:depends-on (:alexandria)
:components ((:file "package")
(:file "core" :depends-on ("package"))))
(asdf:load-system :my-app) loads everything.
For Judge0 we run single-file programs — packages don't really show up. But for any real Lisp project, this is the foundation.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…