Skip to content

normalizes the calls to valueof to three arguments #1670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/features/transforms.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ Plot.valueof(aapl, "Close")
Given an iterable *data* and some *value* accessor, returns an array (a column) of the specified *type* with the corresponding value of each element of the data. The *value* accessor may be one of the following types:

* a string - corresponding to the field accessor (`(d) => d[value]`)
* an accessor function - called as *type*.from(*data*, *value*)
* an accessor function - called on each element as *value*(*element, *index*, *data*)
* a number, Date, or boolean — resulting in an array uniformly filled with the *value*
* an object with a **transform** method — called as *value*.transform(*data*)
* an array of values - returning the same
Expand Down
2 changes: 1 addition & 1 deletion src/channel.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export type ChannelValue =
| number // constant
| boolean // constant
| null // constant
| ((d: any, i: number) => any) // function of data
| ((d: any, i: number, values: any[]) => any) // function of data
| ChannelTransform; // function of data

/**
Expand Down
16 changes: 12 additions & 4 deletions src/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function maybeTypedArrayify(data, type) {
}

function floater(f) {
return (d, i) => coerceNumber(f(d, i));
return (d, i, v) => coerceNumber(f(d, i, v));
}

export const singleton = [null]; // for data-less decoration marks, e.g. frame
Expand Down Expand Up @@ -127,10 +127,18 @@ export function arrayify(data) {
return data == null || data instanceof Array || data instanceof TypedArray ? data : Array.from(data);
}

// An optimization of type.from(values, f): if the given values are already an
// instanceof the desired array type, the faster values.map method is used.
// A generalization of values.map(f) with type conversion: if the given values
// are already an instanceof the desired array type, the faster values.map
// method is used, otherwise type.from is used. If f accepts a third argument,
// it receives the values.
export function map(values, f, type = Array) {
return values == null ? values : values instanceof type ? values.map(f) : type.from(values, f);
return values == null
? values
: values instanceof type
? values.map(f)
: f.length === 3
? type.from(values, (d, i) => f(d, i, values))
: type.from(values, f);
}

// An optimization of type.from(values): if the given values are already an
Expand Down
9 changes: 9 additions & 0 deletions test/options-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@ it("valueof returns the given array value", () => {
assert.strictEqual(valueof([], a), a);
});

it("valueof passes the data as a third argument to function accessors", () => {
const a = (d, i, e) => e.length;
assert.deepStrictEqual(valueof([1, 2], a, Float64Array), Float64Array.of(2, 2));
assert.deepStrictEqual(valueof(Float64Array.of(2, 2), a), [2, 2]);
assert.deepStrictEqual(valueof(Float64Array.of(2, 2), a, Uint8Array), Uint8Array.of(2, 2));
assert.deepStrictEqual(valueof([1, 2], a, Uint8Array), Uint8Array.of(2, 2));
assert.deepStrictEqual(valueof([1, 2], a, Array), [2, 2]);
});

it("valueof accepts complicated data with the proper accessor", () => {
const m = [(d) => d, new Promise(() => {})];
assert.deepStrictEqual(valueof(m, String), ["(d) => d", "[object Promise]"]);
Expand Down