Skip to content

Commit

Permalink
Merge pull request #94 from ds300/boolean-features
Browse files Browse the repository at this point in the history
Boolean and derive features
  • Loading branch information
TrySound committed Nov 15, 2017
2 parents 53f39d0 + 3c7f093 commit 98a49ef
Show file tree
Hide file tree
Showing 11 changed files with 19 additions and 363 deletions.
29 changes: 0 additions & 29 deletions derivable.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@ declare module derivable {
export interface Derivable<T> {

derive<E>(f: (value: T) => E): Derivable<E>;
derive(prop: (string | Derivable<string>)): Derivable<any>;
derive(index: (number | Derivable<number>)): Derivable<any>;
derive(re: (RegExp | Derivable<RegExp>)): Derivable<string[]>;
derive<E>(f: Derivable<(value: T) => E>): Derivable<E>;
derive(args: any[]): Derivable<any>[];
derive<A, E>(f: (value: T, a: A) => E, a: (A | Derivable<A>)): Derivable<E>;
derive<A, B, E>(f: (value: T, a: A, b: B) => E, a: (A | Derivable<A>), b: (B | Derivable<B>)): Derivable<E>;
derive<E>(f: (value: T, ...args: any[]) => E, ...args: any[]): Derivable<E>;
Expand All @@ -33,22 +28,6 @@ declare module derivable {

is(other: any): Derivable<boolean>;

and(other: any): Derivable<any>;

mAnd(other: any): Derivable<any>;

or(other: any): Derivable<any>;

mOr(other: any): Derivable<any>;

then(thenD: any, elseD: any): Derivable<any>;

mThen(thenD: any, elseD: any): Derivable<any>;

not(): Derivable<boolean>;

switch(...args: any[]): Derivable<any>;

withEquality(equals: (a: any, b: any) => boolean): this;
}

Expand Down Expand Up @@ -131,14 +110,6 @@ declare module derivable {

function derive(strings: string[], ...things: any[]): Derivable<string>;

function or(...conditions: any[]): Derivable<any>;

function mOr(...conditions: any[]): Derivable<any>;

function and(...conditions: any[]): Derivable<any>;

function mAnd(...conditions: any[]): Derivable<any>;

function wrapPreviousState<A, B>(fn: (currentState: A, previousState: A) => B, init?: A): (currentState: A) => B;

function captureDereferences(fn: () => void): Derivable<any>[];
Expand Down
36 changes: 0 additions & 36 deletions derivable.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,11 @@
export interface Derivable<T> {

derive<E>(f: (value: T) => E): Derivable<E>;
derive(prop: (string | Derivable<string>)): Derivable<mixed>;
derive(index: (number | Derivable<number>)): Derivable<mixed>;
derive(re: (RegExp | Derivable<RegExp>)): Derivable<Array<string>>;
derive<E>(f: Derivable<(value: T) => E>): Derivable<E>;
derive(args: Array<mixed>): Array<Derivable<mixed>>;
derive<A, E>(f: (value: T, a: A) => E, a: (A | Derivable<A>)): Derivable<E>;
derive<A, B, E>(f: (value: T, a: A, b: B) => E, a: (A | Derivable<A>), b: (B | Derivable<B>)): Derivable<E>;
derive<E>(f: (value: T, ...args: Array<mixed>) => E, ...args: Array<mixed>): Derivable<E>;

mDerive<E>(f: $NonMaybeType<T> => E): Derivable<E>;
mDerive<A>([$NonMaybeType<T> => A]): Derivable<[A]>;
mDerive<A, B>([$NonMaybeType<T> => A, $NonMaybeType<T> => B]): Derivable<[A, B]>;
mDerive<A, B, C>([$NonMaybeType<T> => A, $NonMaybeType<T> => B, $NonMaybeType<T> => C]): Derivable<[A, B, C]>;
mDerive<A, B, C, D>([$NonMaybeType<T> => A, $NonMaybeType<T> => B, $NonMaybeType<T> => C, $NonMaybeType<T> => D]): Derivable<[A, B, C, D]>;
mDerive<A, B, C, D, E>([$NonMaybeType<T> => A, $NonMaybeType<T> => B, $NonMaybeType<T> => C, $NonMaybeType<T> => D, $NonMaybeType<T> => E]): Derivable<[A, B, C, D, E]>;

react(f: (value: T) => void, options?: Lifecycle<T>): void;

Expand All @@ -31,22 +21,6 @@ export interface Derivable<T> {

is(other: mixed): Derivable<boolean>;

and(other: mixed): Derivable<boolean>;

mAnd(other: mixed): Derivable<boolean>;

or(other: mixed): Derivable<boolean>;

mOr(other: mixed): Derivable<boolean>;

then<X, Y>(thenD: X, elseD: Y): Derivable<X | Y>;

mThen<X, Y>(thenD: mixed, elseD: mixed): Derivable<X | Y>;

not(): Derivable<boolean>;

switch(...args: Array<mixed>): Derivable<mixed>;

withEquality(equals: (a: T, b: T) => *): Derivable<T>;
};

Expand Down Expand Up @@ -102,8 +76,6 @@ declare export function derive<T, A, B, C, D>(f: (a: A, b: B, c: C, d: D) => T,

declare export function derive<T>(f: (...args: Array<mixed>)=> T, ...args: Array<mixed>): Derivable<T>

declare export function derive(sections: Array<string>, ...values: Array<mixed>): Derivable<string>

declare export function proxy<T>(proxy: CompositeProxy<T>): Atom<T>;

declare export function transact(f: () => void): void;
Expand All @@ -128,14 +100,6 @@ declare export function isProxy(obj: mixed): boolean;

declare export function derive(strings: Array<string>, ...things: Array<mixed>): Derivable<string>;

declare export function or(...conditions: Array<mixed>): Derivable<boolean>;

declare export function mOr(...conditions: Array<mixed>): Derivable<boolean>;

declare export function and(...conditions: Array<mixed>): Derivable<boolean>;

declare export function mAnd(...conditions: Array<mixed>): Derivable<boolean>;

declare export function wrapPreviousState<A, B>(fn: (currentState: A, previousState: A) => B, init?: A): (currentState: A) => B;

declare export function captureDereferences(fn: () => void): Array<Derivable<mixed>>;
Expand Down
4 changes: 3 additions & 1 deletion src/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
"rules": {
"es5/no-block-scoping": 0,
"es5/no-arrow-functions": 0,
"es5/no-shorthand-properties": 0
"es5/no-shorthand-properties": 0,
"es5/no-rest-parameters": 0,
"es5/no-spread": 0
}
}
28 changes: 0 additions & 28 deletions src/combinators.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,3 @@ export const mMap = (f, derivable) => {
return util.some(arg) ? f(arg) : null;
});
};

function andOrFn (breakOn) {
return function () {
var args = arguments;
return derive(function () {
var val;
for (var i = 0; i < args.length; i++) {
val = unpack(args[i]);
if (breakOn(val)) {
break;
}
}
return val;
});
};
}

function identity (x) { return x; }

function complement (f) { return function (x) { return !f(x); }; }

export var or = andOrFn(identity);

export var mOr = andOrFn(util.some);

export var and = andOrFn(complement(identity));

export var mAnd = andOrFn(complement(util.some));
69 changes: 9 additions & 60 deletions src/derivable.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,18 @@ import {makeReactor} from './reactors';
import * as types from './types';
import {derive as _derive} from './derivation.js';
import {unpack} from './unpack';
import {map, mMap, or, mOr, and, mAnd} from './combinators.js';
import {map, mMap} from './combinators.js';

export var derivablePrototype = {
/**
* Creates a derived value whose state will always be f applied to this
* value
*/
derive: function (f, a, b, c, d) {
var that = this;
switch (arguments.length) {
case 0:
throw new Error('.derive takes at least one argument');
case 1:
if (typeof f === 'function') {
return _derive(f, that);
} else {
if (types.isDerivable(f)) {
return _derive(function () {
var deriver = f.get();
var thing = that.get();
if (typeof deriver === 'function') {
return deriver(thing);
} else {
throw Error('type error');
}
});
} else {
throw Error('type error');
}
}
case 2:
return _derive(f, that, a);
case 3:
return _derive(f, that, a, b);
case 4:
return _derive(f, that, a, b, c);
case 5:
return _derive(f, that, a, b, c, d);
default:
var args = ([f, that]).concat(util.slice(arguments, 1));
return _derive.apply(null, args);
derive: function (f, ...args) {
if (typeof f === 'function') {
return _derive(f, this, ...args);
} else {
throw Error('type error');
}
},

Expand All @@ -68,7 +39,7 @@ export var derivablePrototype = {
} else if (!types.isDerivable(when)) {
throw new Error('when condition must be bool, function, or derivable');
}
mWhen = when.and(mWhen);
mWhen = mWhen.map(d => d && when.get());
}
return this.react(f, util.assign({}, opts, {when: mWhen}));
},
Expand All @@ -80,30 +51,8 @@ export var derivablePrototype = {
});
},

or: function (other) {
return or(this, other);
},

mOr: function (other) {
return mOr(this, other);
},

and: function (other) {
return and(this, other);
},

mAnd: function (other) {
return mAnd(this, other);
},

mDerive: function (arg) {
if (arguments.length === 1 && arg instanceof Array) {
var that = this;
return arg.map(function (a) { return that.mDerive(a); });
} else {
const thenClause = this.derive.apply(this, arguments);
return this.derive(() => this.get() ? thenClause.get() : undefined);
}
mDerive: function (...args) {
return _derive(() => util.some(this.get()) ? this.derive(...args).get() : null);
},

withEquality: function (equals) {
Expand Down
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import * as parents from './parents';
import {deepUnpack, unpack} from './unpack';

export {isDerivable, isAtom, isProxy, isDerivation} from './types';
export {map, mMap, or, mOr, and, mAnd} from './combinators.js';
export {map, mMap} from './combinators.js';
export {transact, transaction, ticker, atomic, atomically} from './transactions';
export {Reactor as __Reactor} from './reactors';

Expand Down
2 changes: 1 addition & 1 deletion test/atom_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ describe('the concurrent modification of _reactors bug', () => {
A_success = true;
}, { from: $A });

const $C = $A.and($B);
const $C = $A.map(a => a && $B.get());

$C.react(() => {
C_success = true;
Expand Down
98 changes: 0 additions & 98 deletions test/combinators_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,104 +78,6 @@ test('maybe map derivable (non-null) value with function', () => {
}
});

test('or function', () => {
const a = derivable.atom(1);
const b = derivable.atom(2);
const c = derivable.atom(3);
const result = derivable.or(a, b, c);
expect(result.get()).toBe(1);

a.set(1);
b.set(0);
c.set(0);
expect(result.get()).toBe(1);

a.set(0);
b.set(2);
c.set(0);
expect(result.get()).toBe(2);

a.set(0);
b.set(0);
c.set(3);
expect(result.get()).toBe(3);

a.set(null);
b.set(0);
c.set(false);
expect(result.get()).toBe(false);
});

test('or method', () => {
const a = derivable.atom(1);
const b = derivable.atom(2);
expect(a.or(b).get()).toBe(1);
});

test('mOr function', () => {
const a = derivable.atom(null);
const b = derivable.atom(0);
const c = derivable.atom(false);
const result = derivable.mOr(a, b, c);
expect(result.get()).toBe(0);

c.set(false);
a.set(null);
b.set(null);
expect(result.get()).toBe(false);
});

test('mOr method', () => {
const a = derivable.atom(null);
const b = derivable.atom(0);
expect(a.mOr(b).get()).toBe(0);
});

test('and function', () => {
const a = derivable.atom(1);
const b = derivable.atom(2);
const c = derivable.atom(3);
const result = derivable.and(a, b, c);
expect(result.get()).toBe(3);

c.set(0);
expect(result.get()).toBe(0);

b.set(false);
expect(result.get()).toBe(false);

a.set(null);
expect(result.get()).toBe(null);
});

test('and method', () => {
const a = derivable.atom(1);
const b = derivable.atom(2);
expect(a.and(b).get()).toBe(2);
});

test('mAnd function', () => {
const a = derivable.atom(1);
const b = derivable.atom(2);
const c = derivable.atom(3);
const result = derivable.mAnd(a, b, c);
expect(result.get()).toBe(3);

b.set(null);
expect(result.get()).toBe(null);

a.set(false);
b.set(false);
c.set(0);
expect(result.get()).toBe(0);
});

test('mAnd method', () => {
const a = derivable.atom(0);
const b = derivable.atom(null);
expect(a.mAnd(b).get()).toBe(null);
});

test('is method', () => {
const a = derivable.atom(1);
const b = derivable.atom(1);
Expand Down
Loading

0 comments on commit 98a49ef

Please sign in to comment.