From 7c2a8b95dc583366dba3f7815c7e933591117757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Fri, 22 Mar 2024 18:58:58 +0100 Subject: [PATCH] An alternative to a Proxy: return an array with a custom property transform, that needs to be invoked when we want to use the data. That means that downstream consumers of this need to know how to handle it. In the tests there is only one case, and it goes through arrayify, which is where I "decode" the structure. Not sure if it's any better. --- src/options.js | 1 + src/transforms/group.js | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/options.js b/src/options.js index 387daa94fb..ce40aa6997 100644 --- a/src/options.js +++ b/src/options.js @@ -132,6 +132,7 @@ export function keyword(input, name, allowed) { // Promotes the specified data to an array as needed. export function arrayify(data) { + if (typeof data?.transform === "function") data = data.transform(); return data == null || data instanceof Array || data instanceof TypedArray ? data : Array.from(data); } diff --git a/src/transforms/group.js b/src/transforms/group.js index d189aa708e..542cf76d96 100644 --- a/src/transforms/group.js +++ b/src/transforms/group.js @@ -66,7 +66,7 @@ function groupn( x, // optionally group on x y, // optionally group on y { - data: reduceData = reduceIdentity, + data: reduceData = reduceIdentityLazy, filter, sort, reverse, @@ -153,6 +153,7 @@ function groupn( groupFacets.push(groupFacet); } maybeSort(groupFacets, sort, reverse); + if (reduceData === reduceIdentityLazy) groupData.transform = () => groupData.map((d) => d()); return {data: groupData, facets: groupFacets}; }), ...(!hasOutput(outputs, "x") && (GX ? {x: GX} : {x1, x2})), @@ -236,6 +237,7 @@ export function maybeGroup(I, X) { export function maybeReduce(reduce, value, fallback = invalidReduce) { if (reduce == null) return fallback(reduce); if (typeof reduce.reduceIndex === "function") return reduce; + if (typeof reduce.reduceIndexLazy === "function") return reduce; if (typeof reduce.reduce === "function" && isObject(reduce)) return reduceReduce(reduce); // N.B. array.reduce if (typeof reduce === "function") return reduceFunction(reduce); if (/^p\d{2}$/i.test(reduce)) return reduceAccessor(percentile(reduce)); @@ -362,8 +364,13 @@ function reduceMaybeTemporalAccessor(f) { export const reduceIdentity = { reduceIndex(I, X) { - let K; // lazy - return new Proxy(I, {get: (I, prop) => (K ??= take(X, I))[prop]}); + return take(X, I); + } +}; + +const reduceIdentityLazy = { + reduceIndex(I, X) { + return () => take(X, I); } };