REW

What Is Null In Scheme?

Published Aug 29, 2025 3 min read
On this page

In Scheme, null refers to the empty list, which is a special, unique object that represents the end of a list. This concept is central to understanding list processing in Scheme and distinguishes it from other Lisp dialects. The empty list is written as the literal '().

The empty list: '()

The empty list, '(), is the value that terminates a proper list. In Scheme, a proper list is either the empty list or a pair whose cdr is a list.

  • Literal representation: You can write the empty list directly as '() in your code. The single quote is important, as () by itself would be interpreted as a procedure call with no arguments, which results in a syntax error.
  • List termination: The cdr of the final pair in a proper list is always '(). For example, the list (a b c) is internally represented as a chain of pairs: (a . (b . (c . '()))).

The null? predicate

To check if a value is the empty list, Scheme provides the built-in predicate null?.

  • Syntax: (null? *obj*)

  • Behavior: It returns #t if obj is the empty list, and #f otherwise. This is the standard and correct way to test for the end of a list in a program.

  • Example:scheme

    (null? '())      ; => #t
    (null? '(1 2 3)) ; => #f
    (null? #f)       ; => #f
    

    Use code with caution.

Scheme vs. Common Lisp: null and nil

One of the most important distinctions to understand is the difference between Scheme and other Lisp dialects, particularly Common Lisp.

Feature Scheme Common Lisp
Empty list A unique, non-boolean object, written as '(). Represented by the symbol nil.
False value A unique object, #f. The same object as the empty list, nil.
Truthiness Everything that is not #f is considered "truthy," including the empty list '(). Only nil is false; everything else is true.
null identifier null is not a standard, built-in identifier. Some implementations, like Racket, define it as an alias for '(). A function null exists to test for nil.

This separation in Scheme is a deliberate design choice to avoid "nil punning," where a single object serves two unrelated purposes (end-of-list and boolean false).

Boolean evaluation of null

Because the empty list '() is distinct from the false value #f, it evaluates differently in a boolean context.

  • In a conditional expression like (if *test* *consequent* *alternative*), '() is treated as a "truthy" value because it is not #f.

  • Therefore, (if '() "true" "false") will evaluate to "true".

  • If you want to check for the empty list in a conditional, you must use the null? predicate.scheme

    (define my-list '())
    (if (null? my-list) "empty" "not empty") ; => "empty"
    

    Use code with caution.

Null pointers and implementation

While from a language perspective, null is the empty list object, its underlying implementation may vary. In some implementations, '() might be a special singleton object that a "null pointer" points to. In others, it might be an immediate, tagged value. Critically, these low-level details do not affect its behavior at the language level. Its purpose remains the same: to terminate a list structure.

Practical implications for list processing

Understanding Scheme's null is vital for writing correct list-processing functions, especially recursive ones. A common recursive pattern for operating on a list looks like this:

(define (list-sum l)
  (if (null? l)
      0 ; Base case: sum of an empty list is 0
      (+ (car l) (list-sum (cdr l))))) ; Recursive step

Use code with caution.

In this example, the null? check correctly identifies the base case for the recursion, stopping when the list is empty. If you were to incorrectly rely on the empty list's "truthiness" in an if expression, your function would fail.

Enjoyed this article? Share it with a friend.