--- name: Common Lisp Ecosystem description: This skill should be used when the user asks to "write common lisp", "CLOS", "ASDF", "defpackage", "defsystem", or works with Common Lisp, SBCL, or Coalton. Provides comprehensive Common Lisp ecosystem patterns and best practices. --- Provide comprehensive patterns for Common Lisp, CLOS, ASDF system definition, SBCL-specific features, and Coalton integration. Read - Analyze ASDF system definitions and Lisp source files Edit - Modify Common Lisp code and system definitions Bash - Run SBCL, Roswell, Qlot commands mcp__context7__get-library-docs - Fetch ASDF, SBCL, and library documentation Homoiconic syntax: code and data share the same structure, enabling powerful macro systems Generic functions with multiple dispatch; method combination (:before, :after, :around) Handler-case for catching, restart-case for recovery points; more powerful than exceptions Namespace management with defpackage; use :import-from or local-nicknames over bare :use Code and data share the same syntax (homoiconicity). Enables powerful macro systems for code transformation. First-class named objects used for identifiers. Interned in packages, can have value, function, and property list. Functions can return multiple values using values, multiple-value-bind, multiple-value-list. Special variables with dynamic scope using defvar/defparameter. Convention: *earmuffs* for special variables. Common Lisp Object System - Generic functions and multiple dispatch Define a class with slots. Slot options: :initarg, :initform, :accessor, :reader, :writer, :type, :documentation. (defclass person () ((name :initarg :name :accessor person-name) (age :initarg :age :accessor person-age)) (:documentation "Represents a person.")) Define generic functions with multiple method implementations. (defgeneric greet (entity) (:documentation "Greet an entity.")) (defmethod greet ((p person)) (format t "Hello, ~a!~%" (person-name p))) Do you need polymorphic behavior based on multiple types? Use defgeneric and defmethod for multiple dispatch Use regular functions for single implementation Method qualifiers (:before, :after, :around) for aspect-oriented programming. (defmethod greet :before ((p person)) (format t "Preparing to greet...~%")) (defmethod greet :around ((p person)) (format t "[Start]~%") (call-next-method) (format t "[End]~%")) Classes can inherit from multiple parent classes. Uses C3 linearization for method resolution order. (defclass employee (person job-holder) ((employee-id :initarg :id :accessor employee-id))) Common Lisp condition system - Restarts and handlers Handle conditions similar to try-catch (handler-case (/ 1 0) (division-by-zero (c) (format t "Caught: ~a~%" c) 0)) Handle conditions without unwinding stack (handler-bind ((error #'(lambda (c) (format t "Error occurred: ~a~%" c) (invoke-restart 'use-value 0)))) (restart-case (error "Something went wrong") (use-value (v) v))) Define recovery points (defun parse-entry (entry) (restart-case (parse-integer entry) (use-value (v) :report "Use a different value" :interactive (lambda () (list (read))) v) (skip-entry () :report "Skip this entry" nil))) Can the error be recovered interactively or programmatically? Provide restarts for different recovery strategies Use handler-case for simple error handling Define custom condition types for structured error handling. (define-condition invalid-input (error) ((value :initarg :value :reader invalid-input-value)) (:report (lambda (c stream) (format stream "Invalid input: ~a" (invalid-input-value c))))) Define packages with explicit dependencies and exports. (defpackage #:my-project (:use #:cl) (:import-from #:alexandria #:when-let #:if-let) (:export #:main #:process-data)) Define local package nicknames for shorter, clearer references. (defpackage #:my-project (:use #:cl) (:local-nicknames (#:a #:alexandria) (#:s #:serapeum))) Another System Definition Facility - Build system for Common Lisp Basic ASDF system definition with metadata and component dependencies. (defsystem "my-project" :description "My project description" :version "0.1.0" :author "Author Name" :license "MIT" :depends-on ("alexandria" "cl-ppcre") :components ((:file "package") (:file "utils" :depends-on ("package")) (:file "main" :depends-on ("utils")))) Organize system components into modules for better structure. (defsystem "my-project" :components ((:module "src" :components ((:file "package") (:file "core" :depends-on ("package")))) (:module "tests" :depends-on ("src") :components ((:file "test-suite"))))) Infer dependencies from defpackage forms for modern, maintainable systems. (defsystem "my-project" :class :package-inferred-system :depends-on ("my-project/main")) ;; In my-project/main.lisp: (defpackage #:my-project/main (:use #:cl) (:import-from #:my-project/utils #:helper)) Do you want automatic dependency inference from package definitions? Use package-inferred-system for modern projects Use traditional defsystem with explicit component dependencies Define test system with automatic test execution using test-op. (defsystem "my-project/test" :depends-on ("my-project" "fiveam") :components ((:file "tests")) :perform (test-op (o s) (uiop:symbol-call :fiveam '#:run! (uiop:find-symbol* '#:my-test-suite :my-project/test)))) Recommended directory layout for Common Lisp projects. my-project/ ├── my-project.asd ├── src/ │ ├── package.lisp │ ├── utils.lisp │ └── main.lisp └── tests/ └── test-suite.lisp Steel Bank Common Lisp - High-performance implementation Create standalone executable with SBCL. (defun main () (format t "Hello, World!~%") (sb-ext:exit :code 0)) (sb-ext:save-lisp-and-die "my-app" :toplevel #'main :executable t :compression t) SBCL threading support with make-thread and mutex synchronization. (defvar *result* nil) (let ((thread (sb-thread:make-thread (lambda () (setf _result_ (heavy-computation))) :name "worker"))) (sb-thread:join-thread thread)) ;; Mutex (defvar _lock_ (sb-thread:make-mutex)) (sb-thread:with-mutex (_lock_) (critical-section)) Call C functions from SBCL using sb-alien interface. (sb-alien:define-alien-routine "strlen" sb-alien:int (str sb-alien:c-string)) (strlen "hello") ; => 5 Use declarations for type information and optimization settings. Options: type, ftype, inline, optimize. (defun fast-add (x y) (declare (type fixnum x y) (optimize (speed 3) (safety 0))) (the fixnum (+ x y))) SBCL-specific extensions for system interaction and performance tuning. ;; Command-line arguments sb-ext:*posix-argv* ;; Execute external programs (sb-ext:run-program "/bin/ls" '("-l")) ;; Trigger garbage collection (sb-ext:gc) ;; POSIX interface: sb-posix ;; Network sockets: sb-bsd-sockets Statically typed functional programming on Common Lisp Define algebraic data types in Coalton with type-safe operations. (coalton-toplevel (define-type (Maybe a) None (Some a)) (declare safe-div (Integer -> Integer -> (Maybe Integer))) (define (safe-div x y) (if (== y 0) None (Some (/ x y))))) Define type classes for polymorphic behavior in Coalton. (coalton-toplevel (define-class (Printable a) (print-it (a -> String))) (define-instance (Printable Integer) (define (print-it x) (into x)))) Coalton compiles to efficient Common Lisp code and is interoperable with regular CL. Use coalton-toplevel for type-safe code sections Coalton functions can call CL functions and vice versa Provides Hindley-Milner type inference with type classes Available Context7 documentation libraries for Common Lisp ecosystem. Common Lisp Docs - General Common Lisp documentation /lisp-docs/lisp-docs.github.io 4.7 580 ASDF - Another System Definition Facility documentation /websites/asdf_common-lisp_dev 7.5 190 SBCL - Steel Bank Common Lisp documentation /sbcl/sbcl 8.0 86 CFFI - Common Foreign Function Interface documentation /websites/cffi_common-lisp_dev 7.5 198 FiveAM - Testing framework documentation /websites/fiveam_common-lisp_dev 7.5 164 Coalton - Statically typed functional programming documentation /coalton-lang/coalton 6.6 568 Use resolve-library-id then get-library-docs for latest documentation. ;; Get ASDF documentation mcp__context7__get-library-docs context7CompatibleLibraryID="/websites/asdf_common-lisp_dev" topic="defsystem" Resource management with unwind-protect for cleanup. (defmacro with-open-socket ((var host port) &body body) `(let ((,var (make-socket ,host ,port))) (unwind-protect (progn ,@body) (close-socket ,var)))) Loop macro for iteration with collection, filtering, and accumulation. (loop for item in list for i from 0 when (evenp i) collect item into evens finally (return evens)) Common format directives: ~a (aesthetic), ~s (standard), ~d (decimal), ~f (float), ~% (newline), ~{~} (iteration), ~[~] (conditional). (format t "~a is ~d years old~%" name age) Document functions with docstrings explaining purpose and parameters. (defun my-function (arg) "Docstring describing the function. ARG is the argument description." (process arg)) Use `*earmuffs*` for special variables Use +plus-signs+ for constants Prefer functional style, minimize mutation Provide restarts for recoverable situations Document exported symbols Use appropriate condition types, not just error Use check-type for argument validation Prefer ASDF package-inferred-system for new projects Consider Qlot for per-project dependency management Use Roswell for portable script execution Use ASDF for all system definitions; never load files directly Provide restarts for recoverable error conditions Document all exported symbols with docstrings Use *earmuffs* for special variables, +plus-signs+ for constants Prefer :import-from over bare :use for clear dependencies Use check-type for argument validation at function boundaries Consider package-inferred-system for new projects Per-project dependency manager (like bundler/npm) Install dependencies from qlfile Run commands with project dependencies qlot install qlot exec ros run Lisp implementation manager and script runner Install Lisp implementations or libraries Start REPL with specified implementation Build standalone executable ros install sbcl ros run ros build myapp.ros Global mutable state makes code harder to test and reason about. Pass state explicitly or use closures to encapsulate mutable state. Using :use for packages other than :cl creates namespace pollution. Use :import-from or package-local-nicknames for clearer dependencies. Ignoring conditions loses error context and recovery opportunities. Handle conditions with handler-case or handler-bind, and provide appropriate restarts. Deeply nested code reduces readability and maintainability. Extract helper functions and use early returns to reduce nesting depth. Using eval in application code is slow and defeats compile-time optimization. Use macros for compile-time code generation or first-class functions for runtime dispatch. Custom reader macros make code harder to read for others. Use reader macros sparingly and document them clearly when necessary. Understand Lisp code requirements 1. Check ASDF system definition 2. Review existing macros and patterns 3. Identify CLOS class hierarchies Write idiomatic Common Lisp code 1. Use appropriate abstraction level 2. Follow condition system for errors 3. Design reusable macros carefully Verify Lisp code correctness 1. Load system with ASDF 2. Run tests with appropriate framework 3. Check for compilation warnings Style inconsistency Fix formatting, follow project conventions Compilation warning or type error Fix issue, add type declarations if needed Macro expansion error Debug with macroexpand, present options to user Reader macro conflict Block operation, require careful namespace management Use ASDF for system definition Follow condition system for error handling Document macros with clear examples Overly complex macros without documentation Global state without clear lifecycle Reader macros without namespace isolation CLOS hierarchy design, system architecture, and package structure planning Common Lisp implementation with proper condition handling and ASDF systems Ensure idiomatic Common Lisp patterns and proper documentation Navigate CLOS hierarchies, generic functions, and symbol definitions Access ASDF, SBCL, and Common Lisp library documentation Debug condition handling, macro expansion, and SBCL-specific issues