Skip to content

Instantly share code, notes, and snippets.

@ehrenmurdick
Last active January 15, 2019 19:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ehrenmurdick/ed0340944e88bde8d540d81ce4bfb87c to your computer and use it in GitHub Desktop.
Save ehrenmurdick/ed0340944e88bde8d540d81ce4bfb87c to your computer and use it in GitHub Desktop.
// @flow
const RED = '\x1b[31m%s\x1b[0m';
const GREEN = '\x1b[32m%s\x1b[0m';
const suite = (tests, failures) => `
${tests} tests, ${failures} faliures
`;
function red(str) {
console.log(RED, str);
}
function green(str) {
console.log(GREEN, str);
}
const msg = (left, right) => `
expected: ${left}
got: ${right}
`;
module.exports = (function() {
let context = {
fails: 0,
firstStack: undefined,
left: undefined,
pass: true,
right: undefined,
tests: 0,
};
console.log();
console.log('come at me tests');
process.on('exit', () => {
let color = green;
if (context.fails > 0) {
color = red;
}
color(suite(context.tests, context.fails));
if (context.fails > 0) {
console.log('the first failing test stack was:');
console.log(context.firstStack);
}
});
return {
test: (str: string, f: () => void) => {
context.pass = true;
f();
if (!context.pass) {
red(str);
console.log(msg(context.left, context.right));
} else {
green(str);
}
},
assert: (left: any, right: any) => {
context.tests++;
let color = green, pass = true;
context.left = left;
context.right = right;
function fail(left, right) {
pass = false;
if (!context.firstStack) {
context.firstStack = new Error(msg(left, right)).stack;
}
};
if (left.constructor == Array) {
if (left.length !== right.length) pass = false;
left.forEach((x, i) => {
if (right[i] !== x) {
fail(left, right);
}
});
} else if (left !== right) {
fail(left, right);
}
if (pass === false) {
context.fails++;
context.pass = false;
color = red;
}
}
}
})();
// @flow
const { assert, test } = require('./easytest');
const _ = require('./stdlib');
test('filter', () => {
const filtered = _.filter(x => x % 2 == 0, [1, 2, 3, 4, 5, 6, 8]);
assert(filtered, [2, 4, 6, 8]);
});
test('foldl', () => {
const folded = _.foldl((s, i) => {
return s + String(i);
}, "", [1, 2, 3, 4, 5, 6]);
assert(folded, '123456');
});
test('map', () => {
const mapped = _.map(x => String(x), [1, 2, 3]);
assert(['1', '2', '3'], mapped);
});
test('prop', () => {
const thing = {a: 'value'};
const geta = _.prop('a');
assert('value', geta(thing));
});
test('prop2', function() {
const thing = {
a: {
b: 'value',
},
};
assert('value', _.prop2('a', 'b')(thing));
});
test('prop3', function() {
const thing = {
a: {
b: {
c: 'value',
}
},
};
assert('value', _.prop3('a', 'b', 'c')(thing));
});
test('lift', () => {
const f = x => x.toString();
const _f = _.lift(f);
const pa = new Promise(res => res('value'));
const pb = _f(pa);
pb.then((v) => {
assert('value', v);
});
});
test('reverse', () => {
const a = [1, 2, 3];
const reversed = _.reverse(a);
assert([3, 2, 1], reversed);
assert([1, 2, 3], a);
});
// @flow
module.exports = {
filter,
foldl,
lift,
map,
prop,
prop2,
prop3,
reverse,
};
function filter<T>(f: T => boolean, xs: Array<T>): Array<T> {
const result: Array<T> = [];
xs.forEach(x => {
if (f(x)) result.push(x);
});
return result;
}
function foldl<A, R>(f: ((R, A) => R), init: R, xs: Array<A>): R {
let cursor = init;
xs.forEach((x) => {
cursor = f(cursor, x);
});
return cursor;
}
function map<T, P>(f: T => P, xs: Array<T>): Array<P> {
return xs.map(f);
}
function prop<O: { +[string]: mixed }, P: $Keys<O>>(
p: P
): (o: O) => $ElementType<O, P> {
// eslint-disable-next-line
return function(o) {
return o[p];
};
}
function prop2<
O2: { +[string]: mixed },
O: { +[string]: O2 },
P: $Keys<O>,
P2: $Keys<O2>,
>(a: P, b: P2): (o: O) => $ElementType<O2, P2> {
// eslint-disable-next-line
return function(o) {
return o[a][b];
};
}
function prop3<
O3: { +[string]: mixed },
O2: { +[string]: O3 },
O: { +[string]: O2 },
P3: $Keys<O3>,
P2: $Keys<O2>,
P: $Keys<O>,
>(a: P, b: P2, c: P3): (o: O) => $ElementType<O3, P3> {
// eslint-disable-next-line
return function(o) {
return o[a][b][c];
};
}
// lift :: ∀ a b f. (a -> b) -> f a -> f b
function lift<A, B>(f: (A => B)): (Promise<A> => Promise<B>) {
return async function(pa) {
const a = await pa;
return f(a);
}
}
function clone<A>(xs: Array<A>): Array<A> {
let ys: Array<A> = [];
xs.forEach(function(x) {
ys.push(x);
});
return ys;
}
function reverse<A>(xs: Array<A>): Array<A> {
return clone(xs).reverse();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment