Created
March 31, 2016 23:36
-
-
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.
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
// 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