Skip to content

Instantly share code, notes, and snippets.

@gordonbrander
Last active August 29, 2023 14:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gordonbrander/591276797f640a77eec1 to your computer and use it in GitHub Desktop.
Save gordonbrander/591276797f640a77eec1 to your computer and use it in GitHub Desktop.
Lua multimethods
--[[
Lua multimethods. Inspired by Clojure's multimethods.
How to use it:
local Multi = require('multimethods')
-- Create a new multimethod and use isa as dispatch function.
-- This will dispatch on first argument by type.
local foo = Multi.create(isa)
-- Creating an implementation for a multimethod is easy... just assign
-- a function at desired key.
function foo.string(x)
print("string!")
end
function foo.number(x)
print("number!")
end
foo('what is this?')
]]--
local exports = {}
-- Create metatable for multimethods.
local Multi = {}
function Multi.__call(t, ...)
-- Generate a key for arguments
local k = t.__dispatch(...)
-- Find the method for key (if any)
local method = t[k]
-- Invoke it with arguments
return method(...)
end
-- Create a new multimethod.
-- It's up to you to provide a dispatch function that can generate a key
-- for a given set of arguments. If a method exists for that key, it will
-- be invoked for those arguments.
local function create(dispatch)
-- Set dispatch function and metatable
return setmetatable({__dispatch = dispatch}, Multi)
end
exports.create = create
-- A fast and simple way to mark different "types" of data.
-- These aren't true types, but they work well enough for Lua.
local function isa(x)
-- If x is a table with a type field, return that as the key.
if type(x) == 'table' and type(x.type) == 'string' then
return x.type
-- Otherwise return the actual type of the data (table, number, string, etc)
else
return type(x)
end
end
exports.isa = isa
return exports
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment