Skip to content

Commit

Permalink
perf(transducers): add IReducible, update reduce()
Browse files Browse the repository at this point in the history
- add IReducible interface for custom/optimized iteration
  and source value provision for reduce()
- add array-like check to reduce() and switch to version without
  forcing array iterator (`for..of..`)
  • Loading branch information
postspectacular committed Aug 22, 2018
1 parent fd8e761 commit 9d83255
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 8 deletions.
4 changes: 4 additions & 0 deletions packages/transducers/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export interface Reducer<A, B> extends Array<any> {
[2]: ReductionFn<A, B>;
};

export interface IReducible<A, B> {
$reduce(rfn: ReductionFn<A, B>, acc: A): A | Reduced<A>;
}

export type TransformFn = (x: any) => any;
export type TransformSubSpec = IObjectOf<TransformSpec | TransformFn>;
export interface TransformSpec extends Array<any> {
Expand Down
3 changes: 2 additions & 1 deletion packages/transducers/src/iterator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export function* iterator<A, B>(xform: Transducer<A, B>, xs: Iterable<A>): Itera
}

/**
* Optimized version of `iterator()` for transducers which are guaranteed to:
* Optimized version of `iterator()` for transducers which are
* guaranteed to:
*
* 1) Only produce none or a single result per input
* 2) Do not require a `completion` reduction step
Expand Down
30 changes: 23 additions & 7 deletions packages/transducers/src/reduce.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { implementsFunction } from "@thi.ng/checks/implements-function";
import { isArrayLike } from "@thi.ng/checks/is-arraylike";
import { illegalArity } from "@thi.ng/errors/illegal-arity";

import { Reducer } from "./api";
import { Reducer, IReducible } from "./api";
import { isReduced, unreduced, Reduced } from "./reduced";

export function reduce<A, B>(rfn: Reducer<A, B>, xs: Iterable<B>): A;
export function reduce<A, B>(rfn: Reducer<A, B>, acc: A, xs: Iterable<B>): A;
export function reduce<A, B>(rfn: Reducer<A, B>, xs: IReducible<A, B>): A;
export function reduce<A, B>(rfn: Reducer<A, B>, acc: A, xs: IReducible<A, B>): A;
export function reduce<A, B>(...args: any[]): A {
let acc: A, xs: Iterable<B>;
let acc: A, xs: Iterable<B> | IReducible<A, B>;
switch (args.length) {
case 3:
xs = args[2];
Expand All @@ -20,11 +24,23 @@ export function reduce<A, B>(...args: any[]): A {
}
const [init, complete, reduce] = args[0];
acc = acc == null ? init() : acc;
for (let x of xs) {
acc = <any>reduce(acc, x);
if (isReduced(acc)) {
acc = (<any>acc).deref();
break;
if (implementsFunction(xs, "$reduce")) {
acc = <any>(<IReducible<A, B>>xs).$reduce(reduce, acc);
} else if (isArrayLike(xs)) {
for (let i = 0, n = xs.length; i < n; i++) {
acc = <any>reduce(acc, xs[i]);
if (isReduced(acc)) {
acc = (<any>acc).deref();
break;
}
}
} else {
for (let x of <Iterable<B>>xs) {
acc = <any>reduce(acc, x);
if (isReduced(acc)) {
acc = (<any>acc).deref();
break;
}
}
}
return unreduced(complete(acc));
Expand Down

0 comments on commit 9d83255

Please sign in to comment.