gensequence
Advanced tools
Comparing version 0.2.4 to 1.0.0
export declare type Maybe<T> = T | undefined; | ||
export interface Sequence<T> extends IterableIterator<T> { | ||
export interface IterableLike<T> { | ||
[Symbol.iterator](): Iterator<T> | IterableIterator<T>; | ||
} | ||
export interface Sequence<T> extends IterableLike<T> { | ||
next(): IteratorResult<T>; | ||
/** map values from type T to type U */ | ||
@@ -24,4 +28,3 @@ map<U>(fnMap: (t: T) => U): Sequence<U>; | ||
} | ||
export interface GenIterable<T> { | ||
[Symbol.iterator](): IterableIterator<T>; | ||
export interface GenIterable<T> extends IterableLike<T> { | ||
} | ||
@@ -40,2 +43,6 @@ export interface SequenceCreator<T> { | ||
export declare function reduce<T, U>(fnReduce: (prevValue: U, curValue: T, curIndex: number) => U, initialValue: U, i: Iterable<T>): U; | ||
/** | ||
* Convert an Iterator into an IterableIterator | ||
*/ | ||
export declare function makeIterable<T>(i: Iterator<T>): IterableIterator<T>; | ||
export declare function scan<T, U>(i: Iterable<T>, fnReduce: (prevValue: U, curValue: T, curIndex: number) => U, initValue: U): IterableIterator<U>; | ||
@@ -58,2 +65,3 @@ /** | ||
*/ | ||
export declare function scanMap<T>(accFn: (acc: T, value: T) => T, init?: T): ((value: T) => T); | ||
export declare function scanMap<T, U>(accFn: (acc: U, value: T) => U, init: U): ((value: T) => U); | ||
@@ -60,0 +68,0 @@ export declare function skip<T>(n: number, i: Iterable<T>): IterableIterator<T>; |
"use strict"; | ||
function genSequence(i) { | ||
return { | ||
function fnNext() { | ||
let iter; | ||
return () => { | ||
if (!iter) { | ||
iter = i[Symbol.iterator](); | ||
} | ||
return iter.next(); | ||
}; | ||
} | ||
const seq = { | ||
[Symbol.iterator]: () => i[Symbol.iterator](), | ||
next: () => i[Symbol.iterator]().next(), | ||
next: fnNext(), | ||
map: (fn) => genSequence(map(fn, i)), | ||
@@ -35,3 +44,3 @@ filter: (fnFilter) => genSequence(filter(fnFilter, i)), | ||
}, | ||
toArray: () => [...i[Symbol.iterator]()], | ||
toArray: () => [...i], | ||
toIterable: () => { | ||
@@ -41,2 +50,3 @@ return toIterator(i); | ||
}; | ||
return seq; | ||
} | ||
@@ -74,11 +84,25 @@ exports.genSequence = genSequence; | ||
exports.reduce = reduce; | ||
/** | ||
* Convert an Iterator into an IterableIterator | ||
*/ | ||
function makeIterable(i) { | ||
function* iterate() { | ||
for (let r = i.next(); !r.done; r = i.next()) { | ||
yield r.value; | ||
} | ||
} | ||
return iterate(); | ||
} | ||
exports.makeIterable = makeIterable; | ||
function* scan(i, fnReduce, initValue) { | ||
let index = 0; | ||
if (initValue === undefined) { | ||
// We need to create a new iterable to prevent for...of from restarting an array. | ||
index = 1; | ||
const r = i[Symbol.iterator]().next(); | ||
const iter = i[Symbol.iterator](); | ||
let r = iter.next(); | ||
if (!r.done) | ||
yield r.value; | ||
initValue = r.value; | ||
if (!r.done) { | ||
yield r.value; | ||
} | ||
i = makeIterable(iter); | ||
} | ||
@@ -85,0 +109,0 @@ let prevValue = initValue; |
{ | ||
"name": "gensequence", | ||
"version": "0.2.4", | ||
"version": "1.0.0", | ||
"description": "Small library to simplify working with Generators and Iterators in Javascript / Typescript", | ||
@@ -12,11 +12,21 @@ "main": "lib/index.js", | ||
"chai": "^3.5.0", | ||
"coveralls": "^2.11.15", | ||
"mocha": "^3.2.0", | ||
"nyc": "^10.1.2", | ||
"rimraf": "^2.5.4", | ||
"typescript": "^2.1.4" | ||
"ts-node": "^2.0.0", | ||
"typescript": "^2.1.5" | ||
}, | ||
"scripts": { | ||
"prepublish": "npm run clean-build && npm test", | ||
"clean-build": "npm run clean && npm run build", | ||
"clean": "rimraf lib", | ||
"test": "mocha lib/**/*.test.js", | ||
"build": "tsc -p .", | ||
"watch": "tsc -w -p ." | ||
"watch": "tsc -w -p .", | ||
"coverage": "npm run generate-code-coverage", | ||
"generate-code-coverage": "NODE_ENV=test nyc npm run test-ts", | ||
"test-ts": "NODE_ENV=test mocha --compilers ts:ts-node/register --recursive \"src/**/*.test.ts\"", | ||
"coverage-coveralls": "nyc report --reporter=text-lcov | coveralls", | ||
"travis-coverage": "npm run generate-code-coverage && npm run coverage-coveralls" | ||
}, | ||
@@ -42,3 +52,19 @@ "repository": { | ||
}, | ||
"nyc": { | ||
"include": [ | ||
"src/**/*.ts" | ||
], | ||
"exclude": [], | ||
"extension": [ | ||
".ts" | ||
], | ||
"require": [ | ||
"ts-node/register" | ||
], | ||
"reporter": [ | ||
"json", | ||
"html" | ||
] | ||
}, | ||
"homepage": "https://github.com/Jason3S/GenSequence#readme" | ||
} |
# GenSequence | ||
[![Build Status](https://travis-ci.org/Jason3S/GenSequence.svg?branch=master)](https://travis-ci.org/Jason3S/GenSequence) | ||
[![Coverage Status](https://coveralls.io/repos/github/Jason3S/GenSequence/badge.svg?branch=master)](https://coveralls.io/github/Jason3S/GenSequence?branch=master) | ||
Small library to simplify working with Generators and Iterators in Javascript / Typescript | ||
@@ -3,0 +7,0 @@ |
import { genSequence, sequenceFromObject, sequenceFromRegExpMatch } from './GenSequence'; | ||
import * as GS from './GenSequence'; | ||
import { expect } from 'chai'; | ||
@@ -152,2 +153,3 @@ | ||
expect(j.map(kvp => kvp[1]).toArray().sort()).to.be.deep.equal(Object.keys(person).map(k => person[k]).sort()); | ||
expect([...GS.objectToSequence(person)]).to.be.deep.equal([...sequenceFromObject(person)]); | ||
}); | ||
@@ -192,2 +194,59 @@ | ||
}); | ||
it('test toIterator', () => { | ||
const seq = genSequence([1, 2, 3]); | ||
const result = [...seq.toIterable()]; | ||
expect(result).to.deep.equal([1, 2, 3]); | ||
}); | ||
it('tests scan', () => { | ||
// let only the first occurrence of a value through. | ||
const seq = genSequence([1, 2, 1, 3, 2, 1, 3]) | ||
.scan((acc, value) => { | ||
const duplicate = acc.s.has(value); | ||
acc.s.add(value); | ||
return {value, duplicate, s: acc.s}; | ||
}, {value: 0, s: new Set<number>(), duplicate: true}) | ||
.filter(acc => !acc.duplicate) | ||
.map(acc => acc.value); | ||
const result = seq.toArray(); | ||
expect(result).to.be.deep.equal([1, 2, 3]); | ||
}); | ||
it('tests scan -- running sum', () => { | ||
// let only the first occurrence of a value through. | ||
const seq = genSequence([1, 2, 1, 3, 2, 1, 3]) | ||
.scan((acc, value) => acc + value); | ||
const result = seq.toArray(); | ||
expect(result).to.be.deep.equal([1, 3, 4, 7, 9, 10, 13]); | ||
}); | ||
it('tests scanMap -- running sum', () => { | ||
// let only the first occurrence of a value through. | ||
const seq = genSequence([1, 2, 1, 3, 2, 1, 3]) | ||
.map(GS.scanMap<number>((acc, value) => acc + value)); | ||
const result = seq.toArray(); | ||
expect(result).to.be.deep.equal([1, 3, 4, 7, 9, 10, 13]); | ||
}); | ||
it('tests scan with no values', () => { | ||
// let only the first occurrence of a value through. | ||
const values: number[] = []; | ||
const seq = genSequence(values) | ||
.scan((acc, value) => acc + value); | ||
const result = seq.toArray(); | ||
expect(result).to.be.deep.equal([]); | ||
}); | ||
it('test the curring part of GS.map', () => { | ||
const fnMap = GS.map((a: number) => 2 * a); | ||
expect(fnMap).to.be.instanceof(Function); | ||
expect([...fnMap([1, 2, 3])]).deep.equal([2, 4, 6]); | ||
}); | ||
it('test getting the iterator from a sequence', () => { | ||
const values = [1, 2, 3, 4]; | ||
expect([...GS.makeIterable(genSequence(values)[Symbol.iterator]())]).to.be.deep.equal(values); | ||
expect([...GS.makeIterable(genSequence(values))]).to.be.deep.equal(values); | ||
}); | ||
}); |
export type Maybe<T> = T | undefined; | ||
export interface Sequence<T> extends IterableIterator<T> { | ||
export interface IterableLike<T> { | ||
[Symbol.iterator](): Iterator<T> | IterableIterator<T>; | ||
} | ||
export interface Sequence<T> extends IterableLike<T> { | ||
next(): IteratorResult<T>; | ||
/** map values from type T to type U */ | ||
@@ -27,5 +32,3 @@ map<U>(fnMap: (t: T) => U): Sequence<U>; | ||
export interface GenIterable<T> { | ||
[Symbol.iterator](): IterableIterator<T>; | ||
} | ||
export interface GenIterable<T> extends IterableLike<T> {} | ||
@@ -38,5 +41,15 @@ export interface SequenceCreator<T> { | ||
export function genSequence<T>(i: GenIterable<T>): Sequence<T> { | ||
return { | ||
function fnNext() { | ||
let iter: Iterator<T>; | ||
return () => { | ||
if(!iter) { | ||
iter = i[Symbol.iterator](); | ||
} | ||
return iter.next(); | ||
}; | ||
} | ||
const seq = { | ||
[Symbol.iterator]: () => i[Symbol.iterator](), | ||
next: () => i[Symbol.iterator]().next(), // late binding is intentional here. | ||
next: fnNext(), // late binding is intentional here. | ||
map: <U>(fn: (t: T) => U) => genSequence(map(fn, i)), | ||
@@ -71,3 +84,3 @@ filter: (fnFilter: (t: T) => boolean) => genSequence(filter(fnFilter, i)), | ||
}, | ||
toArray: () => [...i[Symbol.iterator]()], | ||
toArray: () => [...i], | ||
toIterable: () => { | ||
@@ -77,2 +90,3 @@ return toIterator(i); | ||
}; | ||
return seq; | ||
} | ||
@@ -112,2 +126,14 @@ | ||
/** | ||
* Convert an Iterator into an IterableIterator | ||
*/ | ||
export function makeIterable<T>(i: Iterator<T>) { | ||
function* iterate() { | ||
for (let r = i.next(); ! r.done; r = i.next()) { | ||
yield r.value; | ||
} | ||
} | ||
return iterate(); | ||
} | ||
export function scan<T, U>(i: Iterable<T>, fnReduce: (prevValue: U, curValue: T, curIndex: number) => U, initValue: U): IterableIterator<U>; | ||
@@ -117,8 +143,9 @@ export function* scan<T>(i: Iterable<T>, fnReduce: (prevValue: T, curValue: T, curIndex: number) => T, initValue?: T): IterableIterator<T> { | ||
if (initValue === undefined) { | ||
// We need to create a new iterable to prevent for...of from restarting an array. | ||
index = 1; | ||
const r = i[Symbol.iterator]().next(); | ||
const iter = i[Symbol.iterator](); | ||
let r = iter.next(); | ||
if (!r.done) yield r.value; | ||
initValue = r.value; | ||
if (! r.done) { | ||
yield r.value; | ||
} | ||
i = makeIterable(iter); | ||
} | ||
@@ -177,2 +204,3 @@ let prevValue = initValue; | ||
*/ | ||
export function scanMap<T>(accFn: (acc: T, value: T) => T, init?: T): ((value: T) => T); | ||
export function scanMap<T, U>(accFn: (acc: U, value: T) => U, init: U): ((value: T) => U); | ||
@@ -179,0 +207,0 @@ export function scanMap<T>(accFn: (acc: T, value: T) => T, init?: T): ((value: T) => T) { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
108339
0
129
9
23
875