Skip to content

Commit

Permalink
fix(transducers): #186, Fix crash when using empty string as source f…
Browse files Browse the repository at this point in the history
…or several transducers.
  • Loading branch information
earthlyreason committed Jun 1, 2020
1 parent 1dade92 commit ef7a798
Show file tree
Hide file tree
Showing 34 changed files with 163 additions and 31 deletions.
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/benchmark.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { compR } from "../func/compr";
import { iterator1 } from "../iterator";
import type { Reducer, Transducer } from "../api";
Expand All @@ -21,7 +22,7 @@ import type { Reducer, Transducer } from "../api";
export function benchmark(): Transducer<any, number>;
export function benchmark(src: Iterable<any>): IterableIterator<number>;
export function benchmark(src?: Iterable<any>): any {
return src
return isIterable(src)
? iterator1(benchmark(), src)
: (rfn: Reducer<any, number>) => {
const r = rfn[2];
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/drop-nth.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { isIterable } from "@thi.ng/checks";
import { iterator1 } from "../iterator";
import { throttle } from "./throttle";
import type { Transducer } from "../api";

export function dropNth<T>(n: number): Transducer<T, T>;
export function dropNth<T>(n: number, src: Iterable<T>): IterableIterator<T>;
export function dropNth<T>(n: number, src?: Iterable<T>): any {
if (src) {
if (isIterable(src)) {
return iterator1(dropNth(n), src);
}
n = Math.max(0, n - 1);
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/drop.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { isIterable } from "@thi.ng/checks";
import { compR } from "../func/compr";
import { iterator1 } from "../iterator";
import type { Reducer, Transducer } from "../api";

export function drop<T>(n: number): Transducer<T, T>;
export function drop<T>(n: number, src: Iterable<T>): IterableIterator<T>;
export function drop<T>(n: number, src?: Iterable<T>): any {
return src
return isIterable(src)
? iterator1(drop(n), src)
: (rfn: Reducer<any, T>) => {
const r = rfn[2];
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/duplicate.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { compR } from "../func/compr";
import { iterator } from "../iterator";
import { isReduced } from "../reduced";
Expand All @@ -6,7 +7,7 @@ import type { Reducer, Transducer } from "../api";
export function duplicate<T>(n?: number): Transducer<T, T>;
export function duplicate<T>(n: number, src: Iterable<T>): IterableIterator<T>;
export function duplicate<T>(n = 1, src?: Iterable<T>): any {
return src
return isIterable(src)
? iterator(duplicate(n), src)
: (rfn: Reducer<any, T>) => {
const r = rfn[2];
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/filter.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { compR } from "../func/compr";
import { iterator1 } from "../iterator";
import type { Predicate } from "@thi.ng/api";
Expand All @@ -9,7 +10,7 @@ export function filter<T>(
src: Iterable<T>
): IterableIterator<T>;
export function filter<T>(pred: Predicate<T>, src?: Iterable<T>): any {
return src
return isIterable(src)
? iterator1(filter(pred), src)
: (rfn: Reducer<any, T>) => {
const r = rfn[2];
Expand Down
5 changes: 3 additions & 2 deletions packages/transducers/src/xform/flatten-with.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable, isString } from "@thi.ng/checks";
import { compR } from "../func/compr";
import { iterator } from "../iterator";
import { isReduced } from "../reduced";
Expand All @@ -15,8 +16,8 @@ export function flattenWith<T>(
fn: Fn<T, Iterable<T>>,
src?: Iterable<T | Iterable<T>>
): any {
return src
? iterator(flattenWith(fn), src)
return isIterable(src)
? iterator(flattenWith(fn), isString(src) ? <any>[src] : src)
: (rfn: Reducer<any, T>) => {
const reduce = rfn[2];
const flatten = (acc: any, x: any) => {
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/interleave.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { compR } from "../func/compr";
import { iterator } from "../iterator";
import { isReduced } from "../reduced";
Expand All @@ -10,7 +11,7 @@ export function interleave<A, B>(
src: Iterable<A>
): IterableIterator<A | B>;
export function interleave<A, B>(sep: any, src?: Iterable<A>): any {
return src
return isIterable(src)
? iterator(interleave(sep), src)
: (rfn: Reducer<any, A | B>) => {
const r = rfn[2];
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/interpolate.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { comp } from "../func/comp";
import { normRange } from "../iter/norm-range";
import { iterator } from "../iterator";
Expand Down Expand Up @@ -51,7 +52,7 @@ export function interpolate<T>(fn: Fn2<T[], number, T>, window: number, n: numbe
export function interpolate<T>(fn: Fn2<T[], number, T>, window: number, n: number, src: Iterable<number>): IterableIterator<number>;
// prettier-ignore
export function interpolate<T>(fn: Fn2<T[], number, T>, window: number, n: number, src?: Iterable<number>) {
return src
return isIterable(src)
? iterator(interpolate(fn, window, n), src)
: comp(
partition<T>(window, 1),
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/interpose.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { compR } from "../func/compr";
import { iterator } from "../iterator";
import { isReduced } from "../reduced";
Expand All @@ -10,7 +11,7 @@ export function interpose<A, B>(
src: Iterable<A>
): IterableIterator<A | B>;
export function interpose<A, B>(sep: any, src?: Iterable<A>): any {
return src
return isIterable(src)
? iterator(interpose(sep), src)
: (rfn: Reducer<any, A | B>) => {
const r = rfn[2];
Expand Down
4 changes: 2 additions & 2 deletions packages/transducers/src/xform/labeled.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isFunction } from "@thi.ng/checks";
import { isFunction, isIterable } from "@thi.ng/checks";
import { iterator1 } from "../iterator";
import { map } from "./map";
import type { Transducer } from "../api";
Expand All @@ -11,7 +11,7 @@ export function labeled<L, T>(
src: Iterable<T>
): IterableIterator<[L, T]>;
export function labeled<L, T>(id: LabelFn<L, T>, src?: Iterable<T>): any {
return src
return isIterable(src)
? iterator1(labeled(id), src)
: map(isFunction(id) ? (x: T) => [id(x), x] : (x: T) => [id, x]);
}
5 changes: 4 additions & 1 deletion packages/transducers/src/xform/map-deep.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { deepTransform } from "../func/deep-transform";
import { iterator1 } from "../iterator";
import { map } from "./map";
Expand All @@ -17,5 +18,7 @@ export function mapDeep(
src: Iterable<any>
): IterableIterator<any>;
export function mapDeep(spec: TransformSpec, src?: Iterable<any>): any {
return src ? iterator1(mapDeep(spec), src) : map(deepTransform(spec));
return isIterable(src)
? iterator1(mapDeep(spec), src)
: map(deepTransform(spec));
}
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/map.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { compR } from "../func/compr";
import { iterator1 } from "../iterator";
import type { Fn } from "@thi.ng/api";
Expand All @@ -18,7 +19,7 @@ import type { Reducer, Transducer } from "../api";
export function map<A, B>(fn: Fn<A, B>): Transducer<A, B>;
export function map<A, B>(fn: Fn<A, B>, src: Iterable<A>): IterableIterator<B>;
export function map<A, B>(fn: Fn<A, B>, src?: Iterable<A>): any {
return src
return isIterable(src)
? iterator1(map(fn), src)
: (rfn: Reducer<any, B>) => {
const r = rfn[2];
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/mapcat.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { comp } from "../func/comp";
import { iterator } from "../iterator";
import { cat } from "./cat";
Expand Down Expand Up @@ -33,5 +34,5 @@ export function mapcat<A, B>(
fn: Fn<A, Iterable<B> | null | undefined>,
src?: Iterable<A>
): any {
return src ? iterator(mapcat(fn), src) : comp(map(fn), cat());
return isIterable(src) ? iterator(mapcat(fn), src) : comp(map(fn), cat());
}
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/match-first.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { comp } from "../func/comp";
import { iterator1 } from "../iterator";
import { filter } from "./filter";
Expand Down Expand Up @@ -41,7 +42,7 @@ export function matchFirst<T>(
src: Iterable<T>
): T | undefined;
export function matchFirst<T>(pred: Predicate<T>, src?: Iterable<T>): any {
return src
return isIterable(src)
? [...iterator1(matchFirst(pred), src)][0]
: comp(filter(pred), take(1));
}
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/match-last.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { comp } from "../func/comp";
import { iterator } from "../iterator";
import { filter } from "./filter";
Expand Down Expand Up @@ -41,7 +42,7 @@ export function matchLast<T>(
src: Iterable<T>
): T | undefined;
export function matchLast<T>(pred: Predicate<T>, src?: Iterable<T>): any {
return src
return isIterable(src)
? [...iterator(matchLast(pred), src)][0]
: comp(filter(pred), takeLast(1));
}
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/moving-average.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { illegalArgs } from "@thi.ng/errors";
import { compR } from "../func/compr";
import { iterator1 } from "../iterator";
Expand All @@ -24,7 +25,7 @@ export function movingAverage(period: number): Transducer<number, number>;
// prettier-ignore
export function movingAverage(period: number, src: Iterable<number>): IterableIterator<number>;
export function movingAverage(period: number, src?: Iterable<number>): any {
return src
return isIterable(src)
? iterator1(movingAverage(period), src)
: (rfn: Reducer<any, number>) => {
period |= 0;
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/pad-last.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { iterator } from "../iterator";
import { isReduced } from "../reduced";
import type { Reducer, Transducer } from "../api";
Expand Down Expand Up @@ -41,7 +42,7 @@ export function padLast<T>(
src: Iterable<T>
): IterableIterator<T>;
export function padLast<T>(n: number, fill: T, src?: Iterable<T>): any {
return src
return isIterable(src)
? iterator(padLast(n, fill), src)
: ([init, complete, reduce]: Reducer<any, T>) => {
let m = 0;
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/partition-of.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { iterator } from "../iterator";
import { partitionBy } from "./partition-by";
import type { Transducer } from "../api";
Expand Down Expand Up @@ -26,7 +27,7 @@ export function partitionOf<T>(
src: Iterable<T>
): IterableIterator<T[]>;
export function partitionOf<T>(sizes: number[], src?: Iterable<T>): any {
return src
return isIterable(src)
? iterator(partitionOf(sizes), src)
: partitionBy(() => {
let i = 0,
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/partition-time.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { iterator } from "../iterator";
import { partitionBy } from "./partition-by";
import type { Transducer } from "../api";
Expand Down Expand Up @@ -38,7 +39,7 @@ export function partitionTime<T>(
src: Iterable<T>
): IterableIterator<T[]>;
export function partitionTime<T>(period: number, src?: Iterable<T>): any {
return src
return isIterable(src)
? iterator(partitionTime(period), src)
: partitionBy(() => {
let last = 0;
Expand Down
5 changes: 4 additions & 1 deletion packages/transducers/src/xform/pluck.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { iterator1 } from "../iterator";
import { map } from "./map";
import type { Transducer } from "../api";
Expand All @@ -20,5 +21,7 @@ export function pluck<A, B>(
src: Iterable<A>
): IterableIterator<B>;
export function pluck<A>(key: PropertyKey, src?: Iterable<A>): any {
return src ? iterator1(pluck(key), src) : map((x: any) => x[key]);
return isIterable(src)
? iterator1(pluck(key), src)
: map((x: any) => x[key]);
}
5 changes: 4 additions & 1 deletion packages/transducers/src/xform/select-keys.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { keySelector } from "../func/key-selector";
import { iterator1 } from "../iterator";
import { map } from "./map";
Expand Down Expand Up @@ -33,5 +34,7 @@ export function selectKeys<T>(
src: Iterable<T>
): IterableIterator<any>;
export function selectKeys<T>(keys: PropertyKey[], src?: Iterable<T>): any {
return src ? iterator1(selectKeys(keys), src) : map(keySelector(keys));
return isIterable(src)
? iterator1(selectKeys(keys), src)
: map(keySelector(keys));
}
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/struct.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { comp } from "../func/comp";
import { iterator } from "../iterator";
import { mapKeys } from "./map-keys";
Expand Down Expand Up @@ -52,7 +53,7 @@ export function struct<T>(
src: Iterable<any>
): IterableIterator<T>;
export function struct(fields: StructField[], src?: Iterable<any>): any {
return src
return isIterable(src)
? iterator(struct(fields), src)
: comp(
partitionOf(fields.map((f) => f[1])),
Expand Down
5 changes: 4 additions & 1 deletion packages/transducers/src/xform/swizzle.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { swizzle as _swizzle } from "@thi.ng/arrays";
import { isIterable } from "@thi.ng/checks";
import { iterator1 } from "../iterator";
import { map } from "./map";
import type { Transducer } from "../api";
Expand Down Expand Up @@ -30,5 +31,7 @@ export function swizzle<T>(
src: Iterable<any>
): IterableIterator<any[]>;
export function swizzle(order: PropertyKey[], src?: Iterable<any>): any {
return src ? iterator1(swizzle(order), src) : map(_swizzle(order));
return isIterable(src)
? iterator1(swizzle(order), src)
: map(_swizzle(order));
}
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/take-last.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { __drain } from "../internal/drain";
import { iterator } from "../iterator";
import type { Reducer, Transducer } from "../api";
Expand All @@ -18,7 +19,7 @@ import type { Reducer, Transducer } from "../api";
export function takeLast<T>(n: number): Transducer<T, T>;
export function takeLast<T>(n: number, src: Iterable<T>): IterableIterator<T>;
export function takeLast<T>(n: number, src?: Iterable<T>): any {
return src
return isIterable(src)
? iterator(takeLast(n), src)
: ([init, complete, reduce]: Reducer<any, T>) => {
const buf: T[] = [];
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/take-nth.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { iterator1 } from "../iterator";
import { throttle } from "./throttle";
import type { Transducer } from "../api";
Expand All @@ -17,7 +18,7 @@ import type { Transducer } from "../api";
export function takeNth<T>(n: number): Transducer<T, T>;
export function takeNth<T>(n: number, src: Iterable<T>): IterableIterator<T>;
export function takeNth<T>(n: number, src?: Iterable<T>): any {
if (src) {
if (isIterable(src)) {
return iterator1(takeNth(n), src);
}
n = Math.max(0, n - 1);
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/take.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { compR } from "../func/compr";
import { iterator } from "../iterator";
import { ensureReduced, reduced } from "../reduced";
Expand All @@ -18,7 +19,7 @@ import type { Reducer, Transducer } from "../api";
export function take<T>(n: number): Transducer<T, T>;
export function take<T>(n: number, src: Iterable<T>): IterableIterator<T>;
export function take<T>(n: number, src?: Iterable<T>): any {
return src
return isIterable(src)
? iterator(take(n), src)
: (rfn: Reducer<any, T>) => {
const r = rfn[2];
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/throttle-time.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { iterator1 } from "../iterator";
import { throttle } from "./throttle";
import type { Transducer } from "../api";
Expand All @@ -22,7 +23,7 @@ export function throttleTime<T>(
src: Iterable<T>
): IterableIterator<T>;
export function throttleTime<T>(delay: number, src?: Iterable<T>): any {
return src
return isIterable(src)
? iterator1(throttleTime(delay), src)
: throttle<T>(() => {
let last = 0;
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/xform/throttle.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isIterable } from "@thi.ng/checks";
import { compR } from "../func/compr";
import { iterator1 } from "../iterator";
import type { StatefulPredicate } from "@thi.ng/api";
Expand Down Expand Up @@ -29,7 +30,7 @@ export function throttle<T>(
pred: StatefulPredicate<T>,
src?: Iterable<T>
): any {
return src
return isIterable(src)
? iterator1(throttle(pred), src)
: (rfn: Reducer<any, T>) => {
const r = rfn[2];
Expand Down
Loading

0 comments on commit ef7a798

Please sign in to comment.