Skip to content

Instantly share code, notes, and snippets.

@matthiasak
Created March 31, 2016 23:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthiasak/129712a6b8c37d1a0c5fbaf1f70fb148 to your computer and use it in GitHub Desktop.
Save matthiasak/129712a6b8c37d1a0c5fbaf1f70fb148 to your computer and use it in GitHub Desktop.
Copy the following code into https://matthiasak.github.io/arbiter-frame/#// to see it run.
// simple fn that returns a map node
const node = (val=undefined) => {
let result = {}
if(val) result.val = val
return result
}
// hash fn
const hash = str => {
if(typeof str !== 'string') str = JSON.stringify(str)
const type = typeof str
if (type === 'number') return str
if (type !== 'string') str += ''
let hash = 0
for (let i = 0, len = str.length; i < len; ++i) {
const c = str.charCodeAt(i)
hash = (((hash << 5) - hash) + c) | 0
}
return hash
}
// compare two hashes
const comp = (a,b) => {
return hash(a) === hash(b)
}
// get a sub bit vector
const frag = (h=0, i=0, range=8) =>
(h >>> (range*i)) & ((1 << range) - 1)
const bin = x => (x).toString(2)
// clone a node
const replicate = (o, h) => {
let n = node()
for(var x=0, _o=o, _n=n; x < 4; x++){
for(let i in _o){
if(i !== 'val' && _o.hasOwnProperty(i)){
_n[i] = _o[i] // point n[i] to o[i]
}
}
let __n = node(),
f = frag(h, x)
_n[f] = __n
_n = __n
_o = _o[f] === undefined ? {} : _o[f]
}
return n
}
const set = (m, key, val) => {
let json = JSON.stringify(val),
h = hash(key),
n = get(m, key)
if((n === undefined) || !comp(n, val)){
// in deepest level (3), need to create path down to make this change
let r = replicate(m, h) // new subtree
for(var i=0, _r=r; i<4; i++) _r = _r[frag(h,i)]
_r.val = val
return r
}
// else the hash came out to be the same, do nothing
return m
}
const get = (m, key) => {
let h = hash(key)
for(var i = 0, _r = m; i < 4; i++){
_r = _r[frag(h,i)]
if(!_r) return undefined
}
return _r.val
}
const hashmap = (initial = {}) => {
let result = node()
for(let i in initial){
if(initial.hasOwnProperty(i))
result = set(result, i, initial[i])
}
return result
}
const list = (initial = []) => {
let result = node()
for(let i = 0, len = initial.length; i < len; i++){
result = set(result, i, initial[i])
}
return result
}
const iter = (hashmap,items=[]) => {
for(let i in hashmap){
if(hashmap.hasOwnProperty(i)){
if(i !== 'val'){
iter(hashmap[i], items)
} else {
items.push(hashmap[i])
}
}
}
return items
}
const identity = x=>x
const map = (hashmap, fn=identity) => {
let items = iter(hashmap),
result = []
for(let i=0,len=items.length;i<len;i++){
result.push(fn(items[i]))
}
return result
}
const reduce = (hashmap, fn, acc) => {
let items = iter(hashmap)
acc = (acc === undefined) ? items.shift() : acc
for(let i=0,len=items.length;i<len;i++){
acc = fn(acc, items[i])
}
return acc
}
let x = hashmap({'hello':1})
, y = set(x, 'goodbye', 2)
, z = list([1,2,3])
, a = hashmap({0:1, 1:2, 2:3})
log(
get(x, 'hello')+'',
get(x, 'goodbye')+'',
get(y, 'hello')+'',
get(y, 'goodbye')+'',
x===y,
comp(a,z),
JSON.stringify(a,undefined,4),
map(a, x=>x+1),
reduce(a, (acc,x)=>acc+x, 0)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment