export const keys = (ks, obj) => ks.reduce( (ret, k) => obj.hasOwnProperty(k) ? {...ret, [k]: obj[k]} : ret, {}, ); export const difference = (a, b) => { const diff = new Set(a); for (const el of b) { diff.delete(el); } return diff; }; export const assocIn = (obj, path, value) => path.length === 0 ? obj : path.length === 1 ? { ...obj, [path[0]]: value } : { ...obj, [path[0]]: assocIn( (obj[path[0]] || {}), path.slice(1), value ) }; export const dissoc = (obj, key) => { const ret = { ...obj }; delete ret[key] return ret; }; export const getIn = (obj, path) => path.length === 0 ? obj : getIn(obj?.[path[0]], path.slice(1)); export const findFirst = (arr, fn) => { for (const x of arr) { const ret = fn(x); if (ret) { return ret; } } return null; }; export const partial = (fn, ...startArgs) => (...endArgs) => fn(...startArgs, ...endArgs); export const strSortFn = (a, b) => a.localeCompare(b, "POSIX"); export const undefinedAsNull = x => x === undefined ? null : x; export const first = a => a[0]; export const rest = a => a.slice(1); export const butlast = a => a.slice(a, a.length - 1); export const last = a => a[a.length - 1];