Skip to content


Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time

Build status Coverage Status Chat

C3 superclass linearization

This module is an implementation in Lua of the C3 linearization algorithm.

It extracts super classes with a user-defined function, and handles cycles.

The superclass function takes as input a class, and returns its direct superclasses, from the lowest to the highest priority. The C3 function returns a linearization of the classes, also from the lowest to the highest priority. These orders differ from the one used in the Wikipedia article, but they allow an efficient implementation.


This module is available in luarocks:

    luarocks install c3


First, require this module and create an instance of the algorithm using your own superclass function.

Here, we simply use the identity function for superclass: the superclasses are stored within the class, from 1 (the lowest priority) to n (the highest priority).

    C3 = require "c3"
    c3 = {
      superclass = function (x) return x end,

Then, build the class hierarchy. Here, we follow the example given in Wikipedia. We check that linearization works as expected:

    local o  = {}
    local a  = { o, }
    local b  = { o, }
    local c  = { o, }
    local d  = { o, }
    local e  = { o, }
    local k1 = { c, b, a, }
    local k2 = { e, b, d, }
    local k3 = { d, a, }
    local z  = { k3, k2, k1, }
    local assert = require "luassert"
    assert.are.same (c3 (o ), { o, })
    assert.are.same (c3 (a ), { o, a, })
    assert.are.same (c3 (b ), { o, b, })
    assert.are.same (c3 (c ), { o, c, })
    assert.are.same (c3 (d ), { o, d, })
    assert.are.same (c3 (e ), { o, e, })
    assert.are.same (c3 (k1), { o, c, b, a, k1, })
    assert.are.same (c3 (k2), { o, e, b, d, k2, })
    assert.are.same (c3 (k3), { o, a, d, k3, })
    assert.are.same (c3 (z ), { o, e, c, b, a, d, k3, k2, k1, z, })


Cycles can occur in a class hierarchy. They are handled as expected, by cutting the superclass search when a class has already been encountered.

    local a, b = {}, {}
    a [1] = b
    b [1] = a
    local assert = require "luassert"
    assert.are.same (c3 (a), { b, a, })
    assert.are.same (c3 (b), { a, b, })


Linearization can fail sometimes, but it is quite difficult to get in such cases. The example below creates an error, because we try to linearize a class c with two superclasses with conflicting orders.

    local a, b = {}, {}
    a [1] = b
    b [1] = a
    local c = { a, b, }
    local assert = require "luassert"
    local ok, err = pcall (c3, c)
    assert.is_falsy  (ok)
    assert.is_truthy (err:match "linearization failed")


Linearization uses a cache, that is by default reused between calls. It can be emptied using the clear method.

    c3:clear ()


Tests are written for busted.

  busted src/


Implementation of the C3 linearization algorithm in Lua







No packages published