diff --git a/src/chain-rec.js b/src/chain-rec.js index 0d7c7209..d3c27a93 100644 --- a/src/chain-rec.js +++ b/src/chain-rec.js @@ -1,33 +1,8 @@ -import {Future, Core, isFuture} from './core'; -import {Next, Done, isIteration} from './internal/iteration'; +import {Future, Core} from './core'; +import {Next, Done} from './internal/iteration'; import {Undetermined, Synchronous, Asynchronous} from './internal/timing'; -import {show, showf, noop, partial1} from './internal/fn'; -import {isFunction} from './internal/is'; -import {invalidArgument, typeError} from './internal/throw'; -import {FL, ordinal} from './internal/const'; - -function check$chainRec$future(m, f, i, x){ - if(!isFuture(m)) typeError( - 'Future.chainRec expects the function its given to return a Future every' - + ' time it is called. The value returned from' - + (ordinal[i] ? ` the ${ordinal[i]} call` : ` call ${i}`) - + ' was not a Future.' - + `\n Actual: ${show(m)}\n From calling: ${showf(f)}\n With: (Next, Done, ${show(x)})` - ); -} - -function check$chainRec$it(it, i){ - if(!isIteration(it)) typeError( - 'Future.chainRec expects the function its given to return a Future of an' - + ' Iteration every time it is called. The Future returned from' - + (ordinal[i] ? ` the ${ordinal[i]} call` : ` call ${i}`) - + ' did not resolve to a member of Iteration.' - + '\n You can create an uncomplete or complete Iteration using the next' - + ' or done functions respectively. These are passed into your callback' - + ' as first and second arguments.' - + `\n Actual: Future.of(${show(it)})` - ); -} +import {show, showf, noop} from './internal/fn'; +import {FL} from './internal/const'; export function ChainRec(step, init){ this._step = step; @@ -39,12 +14,10 @@ ChainRec.prototype = Object.create(Core); ChainRec.prototype._fork = function ChainRec$_fork(rej, res){ const {_step, _init} = this; - let i = 0, timing = Undetermined, cancel = noop, state = Next(_init); + let timing = Undetermined, cancel = noop, state = Next(_init); function resolved(it){ - check$chainRec$it(it, i); state = it; - i = i + 1; timing = timing === Undetermined ? Synchronous : drain(); } @@ -52,7 +25,6 @@ ChainRec.prototype._fork = function ChainRec$_fork(rej, res){ while(!state.done){ timing = Undetermined; const m = _step(Next, Done, state.value); - check$chainRec$future(m, _step, i, state.value); cancel = m._fork(rej, resolved); if(timing !== Synchronous){ timing = Asynchronous; @@ -72,14 +44,8 @@ ChainRec.prototype.toString = function ChainRec$toString(){ return `Future.chainRec(${showf(this._step)}, ${show(this._init)})`; }; -function chainRec$step(step, init){ - return new ChainRec(step, init); -} - export function chainRec(step, init){ - if(!isFunction(step)) invalidArgument('Future.chainRec', 0, 'be a Function', step); - if(arguments.length === 1) return partial1(chainRec$step, step); - return chainRec$step(step, init); + return new ChainRec(step, init); } Future[FL.chainRec] = chainRec; diff --git a/test/4.chain-rec.test.js b/test/4.chain-rec.test.js index ab3d145a..cf43e6fb 100644 --- a/test/4.chain-rec.test.js +++ b/test/4.chain-rec.test.js @@ -6,16 +6,9 @@ import type from 'sanctuary-type-identifiers'; describe('chainRec()', () => { - it('is a curried binary function', () => { + it('is a binary function', () => { expect(chainRec).to.be.a('function'); expect(chainRec.length).to.equal(2); - expect(chainRec(U.noop)).to.be.a('function'); - }); - - it('throws TypeError when not given a function', () => { - const xs = [NaN, {}, [], 1, 'a', new Date, undefined, null]; - const fs = xs.map(x => _ => chainRec(x, 1)); - fs.forEach(f => expect(f).to.throw(TypeError, /Future/)); }); it('returns an instance of Future', () => { @@ -36,32 +29,6 @@ describe('ChainRec', () => { describe('#fork()', () => { - it('throws TypeError when the given function does not return a Future', () => { - const xs = [NaN, {}, [], 1, 'a', new Date, undefined, null]; - const fs = xs.map(x => _ => chainRec((a, b, c) => (c, x), 1).fork(U.noop, U.noop)); - fs.forEach(f => expect(f).to.throw(TypeError, /Future.*first call/)); - }); - - it('throws TypeError when the given function does not always return a Future', () => { - const recur = (next, done, i) => i <= 6 ? of(next(i + 1)) : 'hello'; - const f = _ => chainRec(recur, 1).fork(U.noop, U.noop); - expect(f).to.throw(TypeError, /Future.*6/); - }); - - it('throws TypeError when the returned Future does not contain an iteration', () => { - const xs = [null, '', {}, {value: 1, done: 1}]; - const fs = xs.map(x => _ => - chainRec((a, b, c) => of((c, x)), 1).fork(U.noop, U.noop) - ); - fs.forEach(f => expect(f).to.throw(TypeError, /Future.*first call/)); - }); - - it('throws TypeError when the returned Future does not always contain an iteration', () => { - const recur = (a, b, i) => i <= 6 ? of(a(i + 1)) : of('hello'); - const f = _ => chainRec(recur, 1).fork(U.noop, U.noop); - expect(f).to.throw(TypeError, /Future.*6/); - }); - it('does not break if the iteration does not contain a value key', () => { const actual = chainRec((f, g, x) => (x, of({done: true})), 0); return U.assertResolved(actual, undefined);