UNPKG

hexlet-pairs

Version:
85 lines (75 loc) 1.71 kB
// @flow type Message = 'car' | 'cdr'; type Pair = (message: Message) => any; /** * Check if something is pair * @example * const pair = cons(5, 'hello'); * isPair(pair); // true * isPair(5); // false **/ export const isPair = (pair: ?Pair) => typeof pair === 'function' && pair.pair; export const checkPair = (pair: ?Pair) => { if (!isPair(pair)) { const value = typeof pair === 'object' ? JSON.stringify(pair, null, 2) : String(pair); throw new Error(`Argument must be pair, but it was '${value}'`); } }; /** * Build pair * @example * const pair = cons(5, 'hello'); * @example * const pair = cons(cons(1, null), 'world'); **/ export const cons = (a: any, b: any): Pair => { const pair = (message: Message) => { switch (message) { case 'car': return a; case 'cdr': return b; default: throw new Error(`Unknown message '${message}'`); } }; pair.pair = true; return pair; }; /** * Get car (first element) from pair * @example * const pair = cons(5, 'hello'); * car(pair); // 5 **/ export const car = (pair: Pair) => { checkPair(pair); return pair('car'); }; /** * Get cdr (second element) from pair * @example * const pair = cons(5, 'hello'); * cdr(pair); // hello **/ export const cdr = (pair: Pair) => { checkPair(pair); return pair('cdr'); }; /** * Convert pair to string (recursively) * @example * toString(cons('', 10)); // ('', 10) **/ export const toString = (pair: Pair) => { checkPair(pair); const rec = (p) => { if (!isPair(p)) { return String(p); } const left = car(p); const right = cdr(p); return `(${rec(left)}, ${rec(right)})`; }; return rec(pair); };