# Common Lisp Object System (CLOS)

> Source: https://aiwiki.ai/wiki/clos
> Updated: 2026-06-28
> Categories: Programming Languages
> From AI Wiki (https://aiwiki.ai), a free encyclopedia of artificial intelligence. Quote with attribution.

The **Common Lisp Object System** (**CLOS**, often pronounced "see-loss" or "kloss") is the object-oriented programming facility built into ANSI [Common Lisp](/wiki/common_lisp), organized around generic functions and multiple dispatch rather than message passing to a privileged receiver. It was added to the language by a vote of the X3J13 standards committee on June 15, 1988, and is normative in ANSI INCITS 226-1994 (formerly ANSI X3.226-1994), the formal Common Lisp standard [1][4]. CLOS supports multiple inheritance with a deterministic class precedence list, allows complex method combinations (including before, after, and around methods), and exposes a Metaobject Protocol that lets programmers reach into and modify the implementation of the object system itself [2]. In short, CLOS is "the facility for object-oriented programming in ANSI Common Lisp," and is unusual in that any method can specialize on more than one argument, so a single call dispatches on the runtime classes of all of its specialized arguments at once [10].

CLOS grew out of the [Lisp](/wiki/lisp) object systems used in 1980s artificial intelligence research, especially Flavors and New Flavors at the MIT AI Lab and [Symbolics](/wiki/symbolics), and CommonLoops at Xerox PARC [5][6]. It influenced later languages with [multiple dispatch](/wiki/multiple_dispatch), including [Dylan](/wiki/dylan_programming_language), [Julia](/wiki/julia), and the multimethods in [Clojure](/wiki/clojure). [Gregor Kiczales](/wiki/gregor_kiczales), one of CLOS's principal authors, would go on from work on the Metaobject Protocol to develop [aspect-oriented programming](/wiki/aspect_oriented_programming) and AspectJ at Xerox PARC in the late 1990s [8].

## What is CLOS?

A CLOS program is built from four kinds of entities: classes, slots, generic functions, and methods. Classes describe the shape of objects (their slots, which are roughly equivalent to fields in other languages). Generic functions are named operations whose actual behavior depends on the classes of all of their arguments, not just the first one. Methods are pieces of code attached to a generic function and specialized on the classes of one or more arguments. When a generic function is called, CLOS picks the applicable methods, sorts them by specificity, and combines them into an effective method using a method combination strategy.

This is a different shape from the more common object model in [Smalltalk](/wiki/smalltalk), C++, [Python](/wiki/python), or Java, where a method belongs to a class and is invoked by sending a message to an object: `obj.method(args)`. In CLOS, a generic function is a stand-alone function. There is no receiver. Calling `(area shape)` looks up the most specific applicable method based on the class of `shape`; calling `(intersect circle rectangle)` looks it up based on the classes of both `circle` and `rectangle`. The dispatch rule is symmetric across arguments.

CLOS is part of the standard. Any conforming Common Lisp implementation provides it, including SBCL, Clozure CL (CCL), ECL, ABCL, CLISP, GCL, LispWorks, and Allegro Common Lisp. Historically it was also available on Symbolics Genera and on Lucid Common Lisp.

## When was CLOS created, and where did it come from?

### Predecessors: Flavors, New Flavors, and CommonLoops

Lisp had been used for object-oriented programming since the 1970s. The most influential of the early systems was Flavors, developed by Howard Cannon at the MIT Artificial Intelligence Laboratory for the [Lisp Machine](/wiki/symbolics) and Lisp Machine Lisp. Flavors was the first widely used language to feature mixins. It used message passing in the Smalltalk style, but with multiple inheritance, before-daemons and after-daemons, and other features that were unusual for their time [6]. Symbolics adopted Flavors and built much of the Genera operating system on top of it.

Xerox PARC, in parallel, was experimenting with LOOPS (Lisp Object-Oriented Programming System) and then CommonLoops, presented at OOPSLA in 1986 by Daniel G. Bobrow, Kenneth Kahn, Gregor Kiczales, Larry Masinter, Mark Stefik, and Frank Zdybel [5]. CommonLoops is where the generic function model and the heavy use of metaobjects (objects representing classes, methods, and dispatchers) really took shape. As the paper's abstract put it, "CommonLoops blends object-oriented programming smoothly and tightly with the procedure-oriented design of Lisp," so that "message passing is invoked via normal Lisp function call" and "it is easy to incrementally move a program between the procedure and object-oriented styles" [5]. Generic functions are simply Lisp functions; there is no separate message-send protocol.

Between Flavors and CommonLoops sat New Flavors, a redesign of Flavors that replaced message passing with generic functions. This was the bridge: it convinced the Lisp Machine community that giving up the receiver-based model in favor of generic functions was workable.

### The CLOS committee, 1986 to 1988

In 1986, the groups behind New Flavors and CommonLoops met to merge their designs into a single proposal for the X3J13 Common Lisp standardization committee. The principal authors of the resulting CLOS specification were Daniel G. Bobrow and Gregor Kiczales (both Xerox PARC), David A. Moon and Sonya E. Keene (both Symbolics), and Richard P. Gabriel and Linda G. DeMichiel (both Lucid) [1]. The early specification appeared as X3J13 Document 87-002 in 1987. The full specification, often referenced today, was X3J13 Document 88-002R, in three parts: Part 1 covered Programmer Interface Concepts, Part 2 the Functions in the Programmer Interface, and Part 3 the Metaobject Protocol [1].

At its meeting on June 15, 1988, X3J13 voted to adopt Parts 1 and 2 of the CLOS specification (the user-level language) into the draft Common Lisp standard. The adopting motion read: "The X3J13 Committee hereby accepts chapters 1 and 2 of the Common Lisp Object System, as defined in document 88-002R, for inclusion in the Common Lisp language being specified by this committee" [1]. Part 3, the Metaobject Protocol, was deliberately left out of the standard but kept available as a de facto extension implemented by most of the major vendors. The full ANSI Common Lisp standard, INCITS 226-1994 (X3.226-1994), included the CLOS programmer interface as a normative part of the language [4].

### After standardization

In 1991, Kiczales, Jim des Rivières, and Bobrow published *The Art of the Metaobject Protocol* (MIT Press, ISBN 0-262-11158-6 hardcover, 0-262-61074-4 paperback) [2]. The book set out a formal specification of the Metaobject Protocol for CLOS and argued, more broadly, that exposing the design of an object system through reflective hooks is a useful programming language design technique in its own right. Sonya Keene's earlier *Object-Oriented Programming in Common Lisp: A Programmer's Guide to CLOS* (Addison-Wesley, 1989, ISBN 0-201-17589-4) remains the standard tutorial [3].

## What are the core concepts of CLOS?

### Classes and slots

Classes are defined with `defclass`. A class has a name, a list of direct superclasses, and a list of slot specifiers. Slots can have initial values, types, accessor functions, allocation modes (per-instance or per-class), and documentation. Slot accessors come in three flavors: a `:reader` defines a function that reads the slot, a `:writer` defines a function that writes it, and an `:accessor` defines both with the read function and a `(setf accessor)` method.

```lisp
(defclass animal ()
  ((name :initarg :name :reader animal-name)
   (mass :initarg :mass :accessor animal-mass)))

(defclass mammal (animal) ())

(defclass dog (mammal)
  ((breed :initarg :breed :accessor dog-breed)))
```

Classes are themselves first-class objects, instances of a metaclass (`standard-class` by default). The default base class is `standard-object`, which in turn inherits from `t`, the universal class. Almost every Common Lisp built-in type is also a class: `integer`, `string`, `symbol`, and so on are classes you can specialize methods on.

### Generic functions and methods

A generic function is declared with `defgeneric` and acquires methods through `defmethod`.

```lisp
(defgeneric describe-animal (animal))

(defmethod describe-animal ((a animal))
  (format t "~a weighs ~a kg.~%" (animal-name a) (animal-mass a)))

(defmethod describe-animal ((d dog))
  (call-next-method)
  (format t "It is a ~a.~%" (dog-breed d)))
```

The syntax `((a animal))` is a parameter specializer: this method applies when the first argument is an instance of `animal`. The `dog` method is more specific. Calling `(describe-animal fido)` invokes the more specific method, and `call-next-method` runs the next applicable method in the precedence order, much like a `super` call but generalized to arbitrary chains of methods.

### How does multiple dispatch work in CLOS?

The big difference from Smalltalk-style object systems is that any method can specialize on more than one argument, and CLOS dispatches on all of them. As the standard puts it, "methods can be specialized upon any or all of their required arguments," in contrast to single-dispatch languages where "methods are only specialized on the first argument" [10]. A method definition like

```lisp
(defmethod collide ((a asteroid) (s spaceship))
  ...)

(defmethod collide ((s spaceship) (a asteroid))
  ...)

(defmethod collide ((a asteroid) (b asteroid))
  ...)
```

defines three different methods on the same `collide` generic function, each picked based on the runtime classes of both arguments. This is what is meant by [multiple dispatch](/wiki/multiple_dispatch). It is genuinely symmetric: there is no privileged "this" or "self".

Because methods belong to generic functions rather than to classes, there is also no syntactic distinction between "my class's method" and "someone else's method". Anyone can extend a generic function with new methods on their own classes, including methods that specialize on classes from third-party libraries. There is no `private` or `protected`; CLOS does not provide encapsulation by default. Slot access can be restricted by package conventions but is not enforced by the language.

### Method combinations

When several methods are applicable to a call, CLOS combines them into an effective method according to a method combination type. The default is *standard method combination*, which uses four method qualifiers [10].

| Qualifier | Role | Order |
| --- | --- | --- |
| `:before` | Side-effecting setup | All applicable, most specific first |
| primary (no qualifier) | The actual computation | Most specific runs; `call-next-method` continues the chain |
| `:after` | Side-effecting teardown | All applicable, most specific last |
| `:around` | Wraps everything | Most specific runs first; usually delegates with `call-next-method` |

The semantics: all `:before` methods run, in most-specific-first order. Then the most specific primary method runs (and may call `call-next-method` to invoke less specific primaries). Then all `:after` methods run, in most-specific-last order. The value of the primary method becomes the value of the call. If `:around` methods exist, the most specific `:around` runs first and gets full control: only when it calls `call-next-method` do the other methods run at all.

Beyond standard method combination, CLOS provides several short method combinations: `+`, `and`, `or`, `list`, `append`, `nconc`, `min`, `max`, `progn`. With `+` combination, for example, a call returns the sum of the values returned by the applicable methods. Programmers can also define entirely new method combinations with `define-method-combination`, which gives the language something close to user-defined operator overloading at the dispatch level.

### Multiple inheritance and the class precedence list

CLOS supports multiple inheritance. When a class has more than one direct superclass, CLOS computes a class precedence list (CPL) that totally orders the class and all its ancestors. The CPL determines method specificity, slot inheritance, and the order in which `call-next-method` walks through methods.

The CLOS standard specifies an algorithm for computing the CPL that is essentially what was later renamed [C3 linearization](/wiki/c3_linearization). The C3 algorithm itself was described in a 1996 paper by Kim Barrett, Bob Cassels, Paul Haahr, David A. Moon, Keith Playford, and P. Tucker Withington in the context of Dylan, formalizing the same intuition: a class always precedes its direct superclasses, and the order in which superclasses are listed in `defclass` is preserved (the local precedence order) [7]. C3 was later adopted as the default method resolution order in Python 2.3 (2003) and in Raku, among others [7].

The CPL is what makes diamond inheritance well-behaved in CLOS. Slots inherited along multiple paths are merged according to documented rules (most specific writer wins for `:initform`, all type constraints are intersected, and so on).

### Object construction and lifecycle

Instances are created with `(make-instance 'class-name :slot-name value ...)`. CLOS exposes the construction process as a chain of generic functions, each of which can be specialized: `make-instance` calls `allocate-instance` to create the storage, then `initialize-instance`, which by default calls `shared-initialize`. There is also `reinitialize-instance` for resetting slots after creation.

When a class is redefined while instances exist (a common situation in interactive Lisp development, since you are usually editing live code), CLOS does not invalidate the old instances. Instead, when you next touch one, CLOS calls `update-instance-for-redefined-class`, a generic function the programmer can specialize, to migrate the instance to the new shape. The same mechanism, via `update-instance-for-different-class`, supports `change-class`, which transmutes an existing instance into a member of a different class without copying.

## What is the Metaobject Protocol?

The CLOS Metaobject Protocol (MOP) treats the building blocks of CLOS itself, classes, slot definitions, generic functions, and methods, as instances of metaclasses. As the reference description puts it, the MOP "defines a standard interface to the underpinnings of the CLOS implementation, treating classes, slot-descriptions, generic-functions and methods themselves as instances of metaclasses" [10]. Programmers can subclass `standard-class`, `standard-generic-function`, or `standard-method` and override the generic functions that the implementation uses internally to lay out instances, dispatch calls, compute method applicability, walk the class precedence list, and so on [2].

This is not a curiosity. The MOP is how a CLOS programmer adds capabilities the language designers never anticipated, without forking the implementation. Common uses include:

- **Persistence layers** that subclass `standard-class` to intercept slot reads and writes, transparently mapping objects to a database or to disk.
- **Constraint and dependency tracking** systems (the Cells library is the classic example) that turn ordinary slot accesses into dataflow events.
- **Foreign-object wrappers** where an instance of a custom metaclass holds a foreign pointer and lays out its slots in C-compatible memory.
- **AOP-style instrumentation**, where method dispatch is intercepted to add logging, tracing, security checks, or transactions across many functions at once.

The MOP was deliberately kept out of ANSI Common Lisp because it was considered too implementation-sensitive to standardize. In practice, every major Common Lisp implementation supports the MOP described in *The Art of the Metaobject Protocol*, with small portability gaps that the `closer-mop` library smooths over [2][13].

### Reflective architecture

The MOP is reflective in the strict sense: the same generic functions you use to define ordinary classes are also the ones that the system uses internally. Calling `(class-of obj)` gives you a class object you can introspect. Calling `(class-of (class-of obj))` gives you the metaclass. The hierarchy bottoms out: `standard-class` is itself an instance of `standard-class`, so the tower does not require infinite metalevels.

What is unusual about CLOS, compared to languages like Java or [Python](/wiki/python) where reflection is bolted on, is that the reflective interface and the user-facing interface are the same. Specializing `compute-applicable-methods` does not require any special hook; it is just a method definition.

## A small worked example

A small expression tree using inheritance, accessors, and multiple dispatch:

```lisp
(defgeneric evaluate (expr env))

(defclass expression () ())

(defclass literal (expression)
  ((value :initarg :value :reader literal-value)))

(defclass variable (expression)
  ((name :initarg :name :reader variable-name)))

(defclass binary-op (expression)
  ((left  :initarg :left  :reader op-left)
   (right :initarg :right :reader op-right)))

(defclass plus (binary-op) ())
(defclass times (binary-op) ())

(defmethod evaluate ((e literal) env)
  (declare (ignore env))
  (literal-value e))

(defmethod evaluate ((e variable) env)
  (cdr (assoc (variable-name e) env)))

(defmethod evaluate ((e plus) env)
  (+ (evaluate (op-left e) env)
     (evaluate (op-right e) env)))

(defmethod evaluate ((e times) env)
  (* (evaluate (op-left e) env)
     (evaluate (op-right e) env)))

(defmethod evaluate :before ((e expression) env)
  (declare (ignore env))
  (format *trace-output* "Evaluating ~s~%" e))
```

The `:before` method runs before every call to `evaluate` and traces the expression. Because it specializes on the root class `expression`, it applies uniformly to all subclasses. To turn tracing off, you remove that one method; you do not have to change any of the primary methods.

## How does CLOS differ from class-based object systems?

| Aspect | Smalltalk-style OOP (Smalltalk, Java, Python, Ruby, C++) | CLOS |
| --- | --- | --- |
| Method dispatch | Single dispatch on receiver | Multiple dispatch on all specialized arguments |
| Method ownership | Methods belong to classes | Methods belong to generic functions |
| Receiver concept | `self` / `this` is privileged | Symmetric across arguments |
| Inheritance | Single (Java, Smalltalk) or multiple (C++, Python, Eiffel) | Multiple, with C3-style class precedence list |
| Combining inherited methods | `super` call | `call-next-method`, plus before/after/around qualifiers, plus user-defined method combinations |
| Encapsulation | Per-class private/protected/public | None enforced; convention only |
| Class as object | Varies (rich in Smalltalk and Python, weak in Java and C++) | Yes: classes are first-class instances of metaclasses |
| Reflection | Often bolt-on, separate API | Same API as the user-facing language; the MOP is just CLOS |
| Adding methods to existing classes | Often forbidden or awkward | Routine; methods can specialize on built-in or third-party classes |

The absence of encapsulation is a real design choice and not an oversight. CLOS treats classes as data definitions and generic functions as operations on data; it does not bundle them. This is closer in spirit to abstract data types in functional languages than to message-sending OO. It also means CLOS programs are usually more like Lisp programs with a class system attached than they are like Java programs translated into Lisp.

## Which Lisp implementations provide CLOS?

CLOS is part of the ANSI standard, so every conforming Common Lisp provides it [4]. The MOP is not standard but is implemented in some form by all of them.

| Implementation | Status | CLOS / MOP notes |
| --- | --- | --- |
| SBCL (Steel Bank Common Lisp) | Free software, actively developed | Full ANSI CLOS, full AMOP-style MOP |
| CCL (Clozure CL) | Free software, MIT/Apache mix | Full ANSI CLOS, full MOP |
| ECL (Embeddable Common Lisp) | Free software | Full CLOS, MOP with some gaps closed by `closer-mop` |
| ABCL (Armed Bear Common Lisp) | Free software, runs on JVM | Full CLOS, MOP largely supported |
| CLISP | Free software | Full CLOS, extensive MOP |
| GCL (GNU Common Lisp) | Free software | Full CLOS |
| LispWorks | Commercial, Lispworks Ltd. | Full CLOS, full MOP |
| Allegro Common Lisp | Commercial, Franz Inc. | Full CLOS, full MOP, AllegroCache extensions |
| Symbolics Genera | Historical, Symbolics Inc. | CLOS available alongside Flavors |
| Lucid Common Lisp | Historical, Lucid Inc. | One of the original CLOS reference implementations |

The `closer-mop` library by Pascal Costanza papers over differences in MOP support across implementations and is the usual way library code targets multiple Common Lisps when it needs metaprogramming [13].

## How did CLOS influence later languages?

CLOS was developed inside what was, in the late 1980s, the dominant infrastructure for AI research. Common Lisp was the working language at Symbolics, at Xerox PARC, at Lucid, and in many university AI labs. Several ideas that originated or were polished in CLOS later spread well outside the Lisp world.

- **[Dylan](/wiki/dylan_programming_language)**, originally developed at Apple Cambridge in the early 1990s, started as a CLOS-derived language with infix syntax. Dylan refined the class precedence list algorithm, and the C3 paper that resulted was written in the Dylan context [7].
- **[Julia](/wiki/julia)** uses multiple dispatch as its core organizing principle. Methods are attached to generic functions, parameter specializers determine applicability, and the dispatch model is symmetric across arguments. Julia's designers cite CLOS and Dylan as direct ancestors, while noting a key difference: in Julia and Dylan "extensibility is the default" and the built-in functions "are all generic and extensible," whereas in CLOS not every function is a generic function [14].
- **[Clojure](/wiki/clojure)** ships multimethods built on generic functions and a user-supplied dispatch function, with derivation hierarchies that resemble CLOS class precedence. Method combinations in the CLOS sense have been added by libraries such as Methodical.
- **Aspect-oriented programming.** Gregor Kiczales, after working on the CLOS MOP, led the team at Xerox PARC that introduced aspect-oriented programming in 1997 and went on to design AspectJ, an aspect-oriented extension of Java [8]. The intellectual line from MOP method combination to AOP "advice" is direct: before, after, and around methods are essentially the dispatch-time advice that AOP systems generalize across class hierarchies.
- **Method resolution order in [Python](/wiki/python).** Python 2.3 adopted C3 linearization for new-style classes after a 2002 essay by Michele Simionato analyzed it explicitly in CLOS and Dylan terms [7]. Python's `functools.singledispatch`, added in Python 3.4 via PEP 443, is a deliberately small subset of CLOS-style generic functions: it dispatches on the type of the first argument only, whereas CLOS dispatches on any argument [15].
- **Other languages.** Perl 6 / Raku adopted C3, Ruby has CLOS-inspired method-combination libraries, and the open-source CLOS-Like Object System (CLOPS) for [Scheme](/wiki/scheme) and other ports keep showing up because the design is unusually portable.

What keeps CLOS in the conversation is not nostalgia but the fact that the basic design choices, generic functions instead of message passing, multiple dispatch, method combinations, classes as first-class metaobjects, were correct enough that languages designed thirty years later still adopt them one at a time.

## What are the limitations and trade-offs of CLOS?

CLOS is not without rough edges. Its performance model is harder to reason about than single-dispatch OO: dispatch cost depends on the number of applicable methods and on the method combination, and adding a method anywhere can invalidate a dispatch cache. The lack of built-in encapsulation means programmers have to build conventions on top, and the conventions vary across teams. Method combinations and `:around` methods are powerful but can make it hard to read a generic function call in isolation; you may need to inspect every applicable method to know what actually runs. The MOP is a sharp tool: subclassing `standard-class` casually can break compiler optimizations, and AMOP itself spends considerable space on what can and cannot be customized without breaking other parts of the protocol [2].

## ELI5: CLOS in plain terms

In most languages, an object owns its actions: you tell a dog object to `bark()`, and the dog "has" the bark. CLOS flips this around. The action (called a generic function) lives on its own, and you write separate little rules (methods) that say "when the argument is a dog, do this" or "when one argument is an asteroid and the other is a spaceship, do that." Lisp then looks at the actual things you passed in and automatically picks the rule that fits best. Because the action can look at all of its arguments, not just the first one, CLOS can express interactions between two objects (like a collision) naturally, which most object systems make awkward.

## See also

- [Common Lisp](/wiki/common_lisp)
- [Lisp](/wiki/lisp)
- [Multiple dispatch](/wiki/multiple_dispatch)
- [Clojure](/wiki/clojure)
- [Julia](/wiki/julia)
- [Scheme](/wiki/scheme)
- [Symbolics](/wiki/symbolics)
- [Dylan](/wiki/dylan_programming_language)
- [Aspect-oriented programming](/wiki/aspect_oriented_programming)
- [Metaobject protocol](/wiki/metaobject_protocol)
- [C3 linearization](/wiki/c3_linearization)
- [Flavors](/wiki/flavors)
- [CommonLoops](/wiki/commonloops)
- [Gregor Kiczales](/wiki/gregor_kiczales)

## References

1. Bobrow, D. G., DeMichiel, L. G., Gabriel, R. P., Keene, S. E., Kiczales, G., and Moon, D. A. (1988). *Common Lisp Object System Specification*. X3J13 Document 88-002R. Republished in *Lisp and Symbolic Computation*, Volume 1, Number 3-4, January 1989.
2. Kiczales, G., des Rivières, J., and Bobrow, D. G. (1991). *The Art of the Metaobject Protocol*. MIT Press. ISBN 0-262-11158-6 (hardcover), 0-262-61074-4 (paperback).
3. Keene, S. E. (1989). *Object-Oriented Programming in Common Lisp: A Programmer's Guide to CLOS*. Addison-Wesley. ISBN 0-201-17589-4.
4. American National Standards Institute (1994). *American National Standard for Information Technology: Programming Language, Common Lisp*. ANSI INCITS 226-1994 (formerly ANSI X3.226-1994).
5. Bobrow, D. G., Kahn, K., Kiczales, G., Masinter, L., Stefik, M., and Zdybel, F. (1986). "CommonLoops: Merging Lisp and Object-Oriented Programming." *OOPSLA '86 Conference Proceedings*, ACM SIGPLAN Notices, Volume 21, Number 11, pages 17-29.
6. Moon, D. A. (1986). "Object-Oriented Programming with Flavors." *OOPSLA '86 Conference Proceedings*.
7. Barrett, K., Cassels, B., Haahr, P., Moon, D. A., Playford, K., and Withington, P. T. (1996). "A Monotonic Superclass Linearization for Dylan." *OOPSLA '96 Conference Proceedings*.
8. Kiczales, G., Lamping, J., Mendhekar, A., Maeda, C., Lopes, C., Loingtier, J.-M., and Irwin, J. (1997). "Aspect-Oriented Programming." *Proceedings of ECOOP '97*. Springer LNCS 1241.
9. Pitman, K., editor (1994). *Common Lisp HyperSpec*. Online standard reference. Sections on Objects, defclass, defgeneric, defmethod.
10. Wikipedia. "Common Lisp Object System." https://en.wikipedia.org/wiki/Common_Lisp_Object_System
11. Wikipedia. "Flavors (programming language)."
12. Wikipedia. "The Art of the Metaobject Protocol."
13. Costanza, P. "Closer to MOP: A compatibility layer for the CLOS Metaobject Protocol." Software, available at https://github.com/pcostanza/closer-mop.
14. Wikipedia. "Julia (programming language)." https://en.wikipedia.org/wiki/Julia_(programming_language)
15. Python Software Foundation. "PEP 443: Single-dispatch generic functions" and *functools* documentation (singledispatch, added in Python 3.4). https://peps.python.org/pep-0443/

