-- -- melisma - extensible and scriptable audio engine -- Copyright (C) 2026 Ludvig Gunne Lindström -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . -- local m_util = require 'melisma.util' local M = {} function M.fmap(f,l) local res = {} for k,v in pairs(l) do res[k] = f(v) end return res end function M.compose(f,g,...) local tail = table.pack(...) if g == nil then return f end return function(x) return f(M.compose(g,table.unpack(tail))(x)) end end function M.pipeline(...) local args = table.pack(...) return function(x) for _,f in ipairs(args) do x = f(x) end return x end end function M.bind(f,...) local bound = table.pack(...) return function(...) local free = table.pack(...) local all = M.concat(bound,free) return f(table.unpack(all)) end end function M.bind1(f,...) local bound = table.pack(...) return function(x) return f(x,table.unpack(bound)) end end function M.constval(v) return function(...) return v end end function M.constfunc(f) return function(...) f() end end function M.call(f,...) return f(...) end function M.replicate(f,n) local res = {} for i=1,n do if type(f) == 'function' then table.insert(res,f()) else table.insert(res,f) end end return res end function M.id(...) return ... end function M.access(...) local args = table.pack(...) local x = args[#args] args[#args] = nil for _,key in ipairs(args) do x = x[key] end return x end function M.filter(pred,list) local result = {} for _,elem in ipairs(list) do if pred(elem) then table.insert(result,elem) end end return result end function M.void(...) end function M.zip(f,lhs,rhs) local result = {} local n = math.min(#lhs,#rhs) for i = 1,n do local v = f(lhs[i],rhs[i]) table.insert(result,v) end return result end function M.tap(f) return function(...) f(...) return ... end end function M.fold(mempty,mappend,tbl) local result = mempty for i = 1,#tbl do result = mappend(result,tbl) end return result end function M.flatten(tbl) if type(tbl) ~= 'table' then return tbl end return M.fold({}, M.concat, fmap(M.flatten, tbl)) end function M.concat(lhs,rhs) local result = {} for i = 1,#lhs do result[i] = lhs[i] end for i = 1,#rhs do result[i + #lhs] = rhs[i] end return result end function M.find(list,pred) for i = 1,#list do if pred(list[i]) then return list[i],i end end return nil,nil end function M.range(f,t,s) local res = {} for x = f,t,s or 1 do table.insert(res,x) end return res end function M.image(a,b,c,d,x) return (x - a)/(b - a)*(d - c) + c end function M.apply(f,...) return f(...) end function M.once(f) local ret local called = false return function(...) if not called then ret = f(...) called = true return ret end end end return M