// General functions export const _sequential_Q = lst => _list_Q(lst) || _vector_Q(lst) export function _obj_type(obj) { if (_symbol_Q(obj)) { return 'symbol' } else if (_list_Q(obj)) { return 'list' } else if (_vector_Q(obj)) { return 'vector' } else if (_hash_map_Q(obj)) { return 'hash-map' } else if (obj === null) { return 'nil' } else if (obj === true) { return 'true' } else if (obj === false) { return 'false' } else { switch (typeof(obj)) { case 'number': return 'number' case 'function': return 'function' case 'string': return obj[0] == '\u029e' ? 'keyword' : 'string' default: throw new Error(`Unknown type '${typeof(obj)}'`) } } } export function _equal_Q (a, b) { let ota = _obj_type(a), otb = _obj_type(b) if (!(ota === otb || (_sequential_Q(a) && _sequential_Q(b)))) { return false } switch (ota) { case 'list': case 'vector': if (a.length !== b.length) { return false } for (let i=0; i f.ast ? true : false Function.prototype.clone = function() { let that = this // New function instance let f = function (...args) { return that.apply(this, args) } // Copy properties for (let k of Object.keys(this)) { f[k] = this[k] } return f } // Symbols export const _symbol = name => Symbol.for(name) export const _symbol_Q = obj => typeof obj === 'symbol' // Keywords export const _keyword = obj => _keyword_Q(obj) ? obj : '\u029e' + obj export const _keyword_Q = obj => typeof obj === 'string' && obj[0] === '\u029e' // Lists export const _list_Q = obj => Array.isArray(obj) && !obj.__isvector__ // Vectors // TODO: Extend Array when supported export function _vector(...args) { let v = args.slice(0) v.__isvector__ = true return v } export const _vector_Q = obj => Array.isArray(obj) && !!obj.__isvector__ // Hash Maps export const _hash_map = (...args) => _assoc_BANG(new Map(), ...args) export const _hash_map_Q = hm => hm instanceof Map export function _assoc_BANG(hm, ...args) { if (args % 2 === 1) { throw new Error('Odd number of assoc arguments') } // Use iterator/Array.from when it works for (let i=0; i