Skip to content

Instantly share code, notes, and snippets.

@FbN
Created March 9, 2021 14:03
Show Gist options
  • Save FbN/572c3469c8824b4a3fc94a0af572cbaf to your computer and use it in GitHub Desktop.
Save FbN/572c3469c8824b4a3fc94a0af572cbaf to your computer and use it in GitHub Desktop.
Closure Like Protocol
export const f1 = a => a.x
f1.arity = 1
export const f2 = c => a => a.x + c
f2.arity = 2
export const f3 = d => c => a => a.x + c + d
f3.arity = 3
export const f1 = b => b.y
f1.arity = 1
export const f2 = c => b => c + b.y
f2.arity = 2
export const f3 = d => c => b => d + c + b.y
f3.arity = 3
// export const f1 = 'C'
import * as A from './A.js'
import * as B from './B.js'
const a = {
'@@type': 'A',
x: '.A.'
}
const b = {
'@@type': 'B',
y: '.B.'
}
const a2 = {
...a,
x: '.A2.'
}
const protocol = mods => {
const err = m => {
throw new Error(m)
}
const fSet = Object.entries(mods).reduce(
(fSet, [tn, ns]) => ({
...fSet,
...Object.entries(ns).reduce(
(rSet, [fn, f]) => ({
...rSet,
[fn]:
fSet[fn] && fSet[fn] !== f.arity
? err('arity')
: f.arity
}),
{}
)
}),
{}
)
const f = fn => {
!fSet[fn] && err('not implemented')
switch (fSet[fn]) {
case 1:
return v => mods[v['@@type']][fn](v)
case 2:
return v => v2 => mods[v2['@@type']][fn](v)(v2)
case 3:
return v => v2 => v3 => mods[v3['@@type']][fn](v)(v2)(v3)
case 4:
return v => v2 => v3 => v4 =>
mods[v4['@@type']][fn](v)(v2)(v3)(v4)
case 5:
return v => v2 => v3 => v4 => v5 =>
mods[v5['@@type']][fn](v)(v2)(v3)(v4)(v5)
case 6:
return v => v2 => v3 => v4 => v5 => v6 =>
mods[v6['@@type']][fn](v)(v2)(v3)(v4)(v5)(v6)
}
}
return Object.keys(fSet).reduce(
(out, fn) => ({
...out,
[fn]: f(fn)
}),
{}
)
}
const _ = protocol({ A, B })
console.log(_.f1(a), _.f1(b), _.f1(a2))
console.log(_.f2('X')(a), _.f2('Y')(b), _.f2('Z')(a2))
console.log(_.f3('X2')('X')(a), _.f3('Y2')('Y')(b), _.f3('Z2')('Z')(a2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment