Beginner

Hello World in Common Lisp

Your first Common Lisp program - the classic Hello World example with Docker setup

Every programming journey starts with Hello World. Let’s write our first Common Lisp program and experience one of the most powerful and enduring programming languages ever created.

The Code

Create a file named hello.lisp:

1
(format t "Hello, World!~%")

Understanding the Code

Let’s break down this simple but powerful expression:

  • (format t "Hello, World!~%") - In Common Lisp (and all Lisps), code is written as S-expressions using parentheses. The first element is the function name, followed by arguments.
  • format - A powerful built-in function for formatted output, similar to C’s printf but more flexible.
  • t - Represents “true” or standard output (*standard-output*). In Lisp, t is the canonical truth value.
  • "Hello, World!~%" - A format string where ~% is the newline directive.

Why format Instead of print?

Common Lisp actually has multiple output functions:

1
2
3
4
(print "Hello, World!")      ; Prints with quotes and newline
(princ "Hello, World!")      ; Prints without quotes
(write-line "Hello, World!") ; Prints string with newline
(format t "Hello, World!~%") ; Most flexible - formatted output

format is preferred because it provides the most control over output formatting and is the idiomatic choice in Common Lisp.

Running with Docker

The easiest way to run this without installing Common Lisp locally:

1
2
3
4
5
# Pull the SBCL Docker image (Steel Bank Common Lisp)
docker pull clfoundation/sbcl:latest

# Run the program
docker run --rm -v $(pwd):/app -w /app clfoundation/sbcl:latest sbcl --script hello.lisp

Running Locally

If you have SBCL installed:

1
2
3
4
5
6
# Run the script directly
sbcl --script hello.lisp

# Or start the REPL and load interactively
sbcl
# Then type: (load "hello.lisp")

Expected Output

Hello, World!

Understanding S-Expressions

Common Lisp uses prefix notation with parentheses, called S-expressions (symbolic expressions):

1
2
3
4
; Traditional (most languages)     ; Common Lisp
; add(1, 2)                         (+ 1 2)
; print("Hello")                    (print "Hello")
; if (x > 0) then y                 (if (> x 0) y)

The uniform syntax is what makes Lisp’s powerful macro system possible - code and data share the same structure.

Alternative Approaches

Using print Functions

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
;; Using print (adds quotes and newline)
(print "Hello, World!")
;; Output: "Hello, World!"

;; Using princ (no quotes, no newline)
(princ "Hello, World!")
;; Output: Hello, World!

;; Using write-line (no quotes, adds newline)
(write-line "Hello, World!")
;; Output: Hello, World!

Defining a Main Function

For a more structured program:

1
2
3
4
5
(defun main ()
  "A simple Hello World program."
  (format t "Hello, World!~%"))

(main)
  • defun - Defines a function
  • main - The function name (any name works; Common Lisp doesn’t require a specific entry point)
  • () - Empty parameter list
  • "A simple..." - Optional documentation string (docstring)
  • (main) - Calls the function

Using format Directives

The format function is incredibly powerful:

1
2
3
4
5
6
7
8
;; Multiple values
(format t "Hello, ~a!~%" "World")

;; Numbers with formatting
(format t "Pi is approximately ~,2f~%" 3.14159)

;; Multiple arguments
(format t "~a + ~a = ~a~%" 2 3 (+ 2 3))

Common format directives:

  • ~a - Aesthetic (human-readable)
  • ~s - Standard (machine-readable, with quotes for strings)
  • ~d - Decimal integer
  • ~f - Floating point
  • ~% - Newline
  • ~~ - Literal tilde

Key Concepts

  1. S-Expressions - Code is written as nested lists: (function arg1 arg2)
  2. Prefix Notation - The operator/function always comes first
  3. Homoiconicity - Code and data have the same structure (lists)
  4. Dynamic Typing - Types are checked at runtime, not compile time
  5. REPL-Driven - Lisp is designed for interactive development

The REPL Experience

Common Lisp shines in the REPL (Read-Eval-Print Loop):

$ sbcl
This is SBCL 2.4.0, an implementation of ANSI Common Lisp.
* (format t "Hello, World!~%")
Hello, World!
NIL
* (+ 1 2 3)
6
* (defun greet (name) (format t "Hello, ~a!~%" name))
GREET
* (greet "Lisper")
Hello, Lisper!
NIL

The REPL returns two things:

  1. Any output from the expression
  2. The return value (NIL for format since it returns nothing meaningful)

Common Lisp vs Other Languages

Java:

1
2
3
4
5
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

Python:

1
print("Hello, World!")

Clojure (Modern Lisp):

1
(println "Hello, World!")

Common Lisp:

1
(format t "Hello, World!~%")

Notice how Common Lisp is concise like Python but shares the parenthesized syntax with Clojure.

Understanding NIL and T

In Common Lisp, two special values are fundamental:

  • NIL - Represents false, empty list, and “nothing”
  • T - Represents true

In our Hello World:

  • t as the first argument to format means “output to standard output”
  • format returns NIL because its purpose is side effects (printing), not returning a value

Why Common Lisp?

Even in this simple example, we see Common Lisp’s character:

  • Simplicity - Uniform syntax for everything
  • Power - format alone is more powerful than most languages’ output facilities
  • Interactivity - REPL-driven development from the start
  • Documentation - Docstrings are first-class citizens
  • Flexibility - Multiple ways to accomplish the same task

SBCL (Steel Bank Common Lisp)

Our Docker image uses SBCL, which is:

  • Fast - Compiles to native machine code
  • Standard-compliant - Fully implements ANSI Common Lisp
  • Actively maintained - Regular releases with improvements
  • Open source - Derived from CMU Common Lisp

Other implementations exist (CCL, ECL, CLISP), but SBCL is the most popular for general development.

Next Steps

Continue exploring Common Lisp’s unique features:

  • Variables and data types (symbols, lists, vectors)
  • Functions and lambda expressions
  • The powerful format function
  • List processing (car, cdr, cons)
  • Macros - Lisp’s defining feature
  • CLOS - The Common Lisp Object System

Common Lisp rewards patience. Its unusual syntax hides one of the most powerful and flexible programming environments ever created.

Welcome to the world of Lisp!

Running Today

All examples can be run using Docker:

docker pull clfoundation/sbcl:latest
Last updated: