Last active
August 29, 2023 14:34
-
-
Save gordonbrander/591276797f640a77eec1 to your computer and use it in GitHub Desktop.
Lua multimethods
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
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