Skip to content
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

Raise an error when a reducer expects numeric input but is given non-numeric input #487

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Fil
Copy link
Contributor

@Fil Fil commented Aug 7, 2021

Add tests for the normalize transform
closes #473

@Fil Fil requested a review from mbostock August 7, 2021 10:15
Copy link
Member

@mbostock mbostock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ll chip in to help with these.

src/mark.js Outdated
Comment on lines 344 to 105
function isNumeric(values) {
for (const value of values) {
if (value == null) continue;
return !isNaN(+value);
}
}
Copy link
Member

@mbostock mbostock Aug 9, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a slightly different assertion than what we do elsewhere, e.g.:

plot/src/scales.js

Lines 104 to 108 in b1885ad

// If any channel is ordinal or temporal, it takes priority.
const values = channels.map(({value}) => value).filter(value => value !== undefined);
if (values.some(isOrdinal)) return asOrdinalType(key);
if (values.some(isTemporal)) return "utc";
return "linear";

I think what we’re saying here is whether the values are “weakly” numeric, i.e., whether they can be treated as numbers (in this context). So renaming this to isWeaklyNumeric is probably good.

Also, I think we want to treat strict NaN as numeric in this context, since the goal here is to detect things that are not numbers (such as strings), not to check that the numbers themselves are valid. So, one possibility:

Suggested change
function isNumeric(values) {
for (const value of values) {
if (value == null) continue;
return !isNaN(+value);
}
}
function isWeaklyNumeric(values) {
for (const value of values) {
if (value == null) continue;
if (typeof value === "number") return true; // note: includes NaN!
return !isNaN(+value);
}
}

src/mark.js Outdated
Comment on lines 351 to 111
export function checkNumeric(S) {
if (!isNumeric(S)) throw new Error("the reducer expects numeric input");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error message is too specific (referring to a reducer here). I’ll think about this…

@@ -170,9 +170,10 @@ function reduceFunction(f) {
};
}

function reduceAccessor(f) {
function reduceAccessor(f, check) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I’d prefer a separate reduceNumericAccessor here rather than an argument.

@Fil
Copy link
Contributor Author

Fil commented Feb 10, 2022

related #751

@Fil
Copy link
Contributor Author

Fil commented Feb 6, 2023

I've rewritten this PR against main and following your comments.

One thing to note is that we run the test on each call to the reducer. It will usually be fast (returning immediately), so there is no need to memoize, but there might be weird cases (large tables full of null values) where it's not.

@Fil Fil marked this pull request as draft April 3, 2023 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

When a reducer expects numeric input but is given non-numeric input, it should raise an error.
2 participants