UNPKG

functionalscript

Version:

FunctionalScript is a purely functional subset of JavaScript

394 lines (393 loc) 10.1 kB
import { length, concat, countdown, cycle, drop, dropWhile, entries, every, filter, find, flat, flatMap, map, next, reduce, reverse, scan, some, take, takeWhile, toArray, zip, first, filterMap, isEmpty, equal } from "./module.f.js"; import { stringify } from "../../json/module.f.js"; import { sort } from "../object/module.f.js"; import { addition, strictEqual, reduceToScan } from "../function/operator/module.f.js"; const str = sequence => stringify(sort)(toArray(sequence)); const stringifyTest = () => { const s = str([1, 2, 3]); if (s !== '[1,2,3]') { throw s; } }; const cycleTest = () => { const x = str(toArray(take(10)(cycle([1, 2, 3])))); if (x !== '[1,2,3,1,2,3,1,2,3,1]') { throw x; } }; const countdownTest = () => { const result = str(countdown(10)); if (result !== '[9,8,7,6,5,4,3,2,1,0]') { throw result; } }; const flatTest = () => { const result = str(flat([[1, 2, 3], [4, 5], [6], [], [7, 8, 9]])); if (result !== '[1,2,3,4,5,6,7,8,9]') { throw result; } }; const concatTest = () => { const result = concat([1])([2]); const x = next(result); if (x === null) { throw x; } if (x.first !== 1) { throw x; } }; const flatMapTest = () => { const result = str(flatMap((x) => [x, x * 2, x * 3])([0, 1, 2, 3])); if (result !== '[0,0,0,1,2,3,2,4,6,3,6,9]') { throw result; } }; const takeTest = [ () => { const result = str(take(3)([1, 2, 3, 4, 5, 6, 7, 8, 9])); if (result !== '[1,2,3]') { throw result; } }, () => { const result = str(take(20)([1, 2, 3, 4, 5, 6, 7, 8, 9])); if (result !== '[1,2,3,4,5,6,7,8,9]') { throw result; } }, () => { const result = str(take(0)([1, 2, 3, 4, 5, 6, 7, 8, 9])); if (result !== '[]') { throw result; } } ]; const findTest = [ () => { const result = find(null)((x) => x % 2 === 0)([1, 3, 5, 7]); if (result !== null) { throw result; } }, () => { const result = find(null)((x) => x % 2 === 0)([1, 2, 3, 4]); if (result !== 2) { throw result; } } ]; const takeWhileTest = [ () => { const result = str(takeWhile((x) => x < 10)([1, 2, 3, 4, 5, 10, 11])); if (result !== '[1,2,3,4,5]') { throw result; } }, () => { const result = str(takeWhile((x) => x < 6)([1, 2, 3, 4, 5, 6, 7, 8, 9])); if (result !== '[1,2,3,4,5]') { throw result; } } ]; const dropWhileTest = () => { const result = str(dropWhile((x) => x < 10)([1, 2, 3, 4, 5, 10, 11])); if (result !== '[10,11]') { throw result; } }; const dropTest = [ () => { const result = str(drop(3)([1, 2, 3, 4, 5, 10, 11])); if (result !== '[4,5,10,11]') { throw result; } }, () => { const result = str(drop(0)([1, 2, 3, 4, 5, 10, 11])); if (result !== '[1,2,3,4,5,10,11]') { throw result; } }, () => { const result = str(drop(10)([1, 2, 3, 4, 5, 10, 11])); if (result !== '[]') { throw result; } } ]; const additionTests = [ () => { const op = reduceToScan(addition); const result = str(scan(op)([2, 3, 4, 5])); if (result !== '[2,5,9,14]') { throw result; } }, () => { const result = reduce(addition)(null)([2, 3, 4, 5]); if (result !== 14) { throw result; } }, () => { const result = reduce(addition)(null)([]); if (result !== null) { throw result; } } ]; const entriesTest = [ () => { const result = str(entries([])); if (result !== '[]') { throw result; } }, () => { const result = str(entries(['hello', 'world'])); if (result !== '[[0,"hello"],[1,"world"]]') { throw result; } } ]; const reverseTest = [ () => { const result = str(reverse([])); if (result !== '[]') { throw result; } }, () => { const result = str(reverse([1, 2, 3, 4, 5])); if (result !== '[5,4,3,2,1]') { throw result; } } ]; const zipTest = [ () => { const result = str(zip([0, 1, 2])(['a', 'b', 'c', 'd'])); if (result !== '[[0,"a"],[1,"b"],[2,"c"]]') { throw result; } }, () => { const result = str(zip([0, 1, 2])(['a', 'b'])); if (result !== '[[0,"a"],[1,"b"]]') { throw result; } } ]; const logic = () => { const map5 = map((x) => x > 5); return [ () => { const result = some(map5([0, 1, 7])); if (!result) { throw result; } }, () => { const result = some(map5([0, 1, 4])); if (result) { throw result; } }, () => { const result = some(map5([])); if (result) { throw result; } }, () => { const result = every(map5([0, 1, 7])); if (result) { throw result; } }, () => { const result = every(map5([6, 11, 7])); if (!result) { throw result; } }, () => { const result = every(map5([])); if (!result) { throw result; } } ]; }; // stress tests const stress = () => ({ toArray: () => { // 200_000_000 is too much const n = 100_000_000; const result = toArray(countdown(n)); if (result.length !== n) { throw result.length; } const len = length(filter((x) => x > n)(result)); if (len !== 0) { throw len; } }, first: () => { // 100_000_000 is too much const n = 50_000_000; const result = toArray(countdown(n)); if (result.length !== n) { throw result.length; } const f = first(null)(result); if (f !== n - 1) { throw f; } }, concatBack: () => { let sequence = []; // 20_000_000 is too much // 10_000_000 is too much for Deno 1 for (let i = 0; i < 5_000_000; ++i) { sequence = concat(sequence)([i]); } const r = toArray(sequence); }, flatToArray: () => { let sequence = []; // 4_000_000 is too much for (let i = 0; i < 2_000_000; ++i) { sequence = flat([sequence, [i]]); } const r = toArray(sequence); }, flatNext: () => { let sequence = []; // 4_000_000 is too much for (let i = 0; i < 2_000_000; ++i) { sequence = flat([sequence, [i]]); } const a = next(sequence); }, concatFront: () => { let sequence = []; // 20_000_000 is too much for (let i = 0; i < 10_000_000; ++i) { sequence = concat([i])(sequence); } const a = next(sequence); }, flatFront: () => { let sequence = []; // 10_000_000 is too much for (let i = 0; i < 5_000_000; ++i) { sequence = flat([[i], sequence]); } const a = next(sequence); }, filterMap: () => { // 100_000_000 is too much const n = 50_000_000; const result = toArray(countdown(n)); if (result.length !== n) { throw result.length; } const len = length(filterMap(() => null)(result)); if (len !== 0) { throw len; } }, dropWhile: () => { // 50_000_000 is too much const n = 20_000_000; const result = toArray(countdown(n)); if (result.length !== n) { throw result.length; } const len = length(dropWhile(() => true)(result)); if (len !== 0) { throw len; } }, reverse: () => { // 10_000_000 is too much const n = 5_000_000; const result = toArray(reverse(countdown(n))); if (result.length !== n) { throw result.length; } } }); export default { stringifyTest, cycle: cycleTest, countdown: countdownTest, flat: flatTest, concat: concatTest, flatMap: flatMapTest, take: takeTest, find: findTest, takeWhile: takeWhileTest, dropWhile: dropWhileTest, drop: dropTest, additionTests, entries: entriesTest, reverse: reverseTest, zip: zipTest, logic, strictEqual: [ () => { const result = equal(strictEqual)([1])([2, 3]); if (result) { throw result; } }, () => { const result = equal(strictEqual)([1, 3])([1]); if (result) { throw result; } }, () => { const result = equal(strictEqual)([15, 78])([15, 78]); if (!result) { throw result; } }, () => { const result = equal(strictEqual)([])([]); if (!result) { throw result; } } ], isEmpty: [ () => { const result = isEmpty(() => []); if (result !== true) { throw result; } }, () => { const result = isEmpty(() => [2]); if (result !== false) { throw result; } } ], length: () => { if (length([1, 2, 3]) !== 3) { throw 3; } if (length(null) !== 0) { throw 0; } if (length(flat([[1, 3], null, () => [3], concat([12])([4, 89])])) !== 6) { throw 6; } }, // stress };