76 comments

[ 3.0 ms ] story [ 148 ms ] thread
I honestly don't know what's worse; That this package exists, or that the implementation requires a dependency to `is-odd` and just does `return !isOdd(number)`
IIRC it’s the same author, and designed this way to farm downloads.
From GitHub:

"Several years ago, just before my 40th birthday, I switched careers from sales, marketing and consulting to learn how to program, with the goal of making the world a better place through code. Whether that means giving people access to information, the tools and technology to level the playing field with big corporations, or empowering people in impoverished regions to participate in the world economy.

To date, I've created more than 1,000 open source projects in an effort to reach my goal. Open source software takes a lot of time to create and maintain, and millions of projects now depend on my code. You can help me to achieve my goals of improving the world through code, help me create better developer experiences, or just say "thank you" by sponsoring me on GitHub. Any and all contributions are greatly appreciated."

The author is notorious for flooding npm with small packages like this.
> (This project's readme.md is generated by verb, please don't edit the readme directly. Any changes to the readme must be made in the .verb.md readme template.)

What's worse is that it comes with a special generated readme page.

(comment deleted)
this just must be a joke package, as all it is doing is importing an "is-odd" package and returning `!isOdd(i)`... sad to think that someone is actually using this though.
According to the readme it was a package he created back in 2014 when first learning programming and wanted to work out how to create JS packages, and then it somehow exploded and took on a life of its own.
It even depends on is-odd (375K weekly downloads). The script kiddies have taken over.
Hopefully is-odd does not depend on is-even
It actually depends on "is-number", which is a very useful package containing

   num => typeof num === "number"
No joke.
To be completely fair, it does a little bit more than that. It only considers finite numbers as 'numbers' (ie NaN and Inf aren't considered numbers). It also considers strings that can be parsed as numbers as numbers. Of course reasonable people could consider both those 'features' as bugs
Which in itself depends on is-number (66M weekly downloads).

The beautiful journey seems to end there.

https://www.npmjs.com/package/is-number

Which used to depend on the legendary `is-is` package. Apparently the maintainer is a certain B. Clinton.
Wow! there are almost 2500 packages on npm that depends on is-number. That's insane.
Combining that with https://www.npmjs.com/package/is-string, you can have a JavaScript valid x for which

  isNumber(x) && isString(x)
isNumber is better named “can-be-used-as-a-number”.

Also, I don’t know JavaScript well enough, but https://www.npmjs.com/package/isnumber is different code from https://www.npmjs.com/package/is-number, but does it have different semantics?

(https://www.npmjs.com/package/lodash.isnumber is different, I think. It (rightfully, IMHO) thinks ∞ and NaN are numbers)

Am I missing something here, why is a package even needed needed for this? Can you not evaluate `some_int % 2` in Javascript to check for this directly?
Javascripts habit of coercing values when you don't want it too would make this presumably a little suspect?

Even so: I'd much rather in my code have a function doing exactly this, rather then peppering it all through my code anyway.

Sure, but that doesn't justify an external dependency
It seems to be a culture things in the JS world. Packaging just 1 or 2 functions as its own separate package and using large chains of dependancies is just the way they do things. In most other languages, if this function existed, it would either be in the standard library or be a tiny part of a single number manipulating library with 100s of functions.
I’m going to create my magnum opus tonight

“isZero”

Which checks if a number is 0

By checking that the number is equal to its negative?
Oh yeah, Imma do the most Hacker News I can think of and re-impl both packages in Rust. Better yet I might fire up PyTorch and develop some ML solution to recognize even/oddness. There really are more choices for this than I though at first.
And publish some NN solution on public repo like huggingface.co.
If we're going to build any of these we're going to really need to do some testing too. That means we need a suitably reliable generator of numbers known to be positive or negative.
I think that isFourtyTwo is free.
When it just appeared I thought it was a joke, but it seems people actually use this...
Quite a while back, I once saw a front-end engineer copy-pasting every bit of the CSS that he wrote. So, I asked, “Won’t it be faster if you just typed?” “I want to avoid errors.”
And the source repository was archived in 2019.
With so many developers using this package there must be a few here on HN. If anyone here has included this as a dependency I'd love to know the reasoning behind it.
To prove a point that download counters are useless I wrote this: https://pypi.org/project/pypular/

Takes me about 7 minutes at home to trigger 1 million fake downloads.

I want to use http2 to send less headers and be able to do that in less time.

> download counters are useless

Unless they apply some kind of filtering to discount requests from the same source. If each source address were to only count as a single download once per period and a period was 20 minutes, your million fake downloads if from a single source would be forced to not take 38 years rather than 7 minutes.

They would not. In most cases downloads come from a badly setup CI that re-downloads the same thing tens of thousands of times per day. It's incredibly common for them to come from the same source.

It would make sense but ALL the project counters would go down by a lot.

You can fake counts up but not down. I think it can make a decent measure of popularity where there’s disincentive to be popular (like pypi security). You can set a point where you’ll catch almost all the truly popular packages, plus a small portion of the non-popular. (Although, the ratio of true positive to false positive may be way off, that’s the nature of things with low prevalence).
A large bulk of those downloads are coming from downstream packages (handlebars-helpers), I don’t think developers are pulling this in directly.
Would be nice if npm differentiated direct downloads from indirect downloads as a dependency.
Maybe a bit off topic but who is paying to host these services?
Microsoft, as they have acquired both github and npm
Dart has a lot of built-in methods similar to this. Yes, that includes `$n.isEven` and `$n.isOdd`. It's especially nice with iterables that have `.isEmpty` and `.isNotEmpty`. I make regular use of all four. It cuts down on clutter and makes the intent unmistakably clear. I think these JS packages, and Dart's inclusion of them in the stdlib are indicative of a clear need among programmers for unambiguous intention. Also, I suspect a lot of people, especially JS programmers, of whom a large percent is certainly made up of non-formally educated people, likely don't know that testing for even-ness can be done with modulo.

All of this is to say, instead of this being an indictment of the JS ecosystem and its programmers, its more indicative of a stdlib function that should exist but doesn't.

(comment deleted)
Is N%2==0 ambiguous for you?
To me? No. But its extra characters that I need to scan and process, it's syntax that can't be autocompleted by my LSP/IDE, and it's at least one mental leap away from what I really want to do. I am interested in the even-ness, not the remainder.

The simpler programming can be made to be, the better. I'm not going to die on the anti-modulo hill, I don't care that much about it. But I think it's silly to pretend that it's not overly complicated (even if only a little) for the task most commonly at hand.

>All of this is to say, instead of this being an indictment of the JS ecosystem and its programmers, its more indicative of a stdlib function that should exist but doesn't.

Surely by now they would have recognised a need for some standard math packages and then created one and all the new projects should be using that and people would have migrated? Especially given how fast FE seems to move.

Instead they are content with pulling a thousand dependencies and an intractable dependency system.

I'd say there's a reasonable middle ground here where you can define isOdd where you need it:

    isOdd = x => x % 2 === 1
    ...
It's one of those things that doesn't pop up all that often and never changes. I've looked through my whole codebase and there are 3 occurrences.

Aside: I don't use Dart, but does that mean that you have to rely on each different type of iterable to implement these functions?

I don't quite know what you mean by "rely on" here, but the isEmpty fields are implemented on the iterator interface, so any of the standard container types implement it by default, including lists, sets, and maps.

Also to address other posts in the thread, while I don't think this specific example is worth indicting JS developers over, I do think the culture of infinite dependencies common to JS developers is. This shouldn't be an entire additional dependency. Just implement the modulo operation, or as parent suggests, make a nicely named utility function that wraps the modulo operation. But when the culture strongly encourages downloading micro packages for every little thing, I can hardly blame them for adding this into the pile of yet more things they've downloaded.

Ahhh, I see my confusion here. Got mixed up with the abstractions (isEven != isEmtpy) and thought there was something crazy going on with lists of numbers implementing isEmpty.

On the whole I do agree with you about all this mess. The JS stdlib has a lot to answer for.

Not defending isOdd in any way, but the example shows that even something as clear-cut as testing a number for oddness isn't that easy to get right:

isOdd(-1) === false

(-1 % 2 === -1)

Ha! Good catch. You’d think that with a math degree including algebraic number systems I would have spotted that.
Is there an easy way to trace the most popular packages that use it?
Sadly not and I think this is an important question because I’m sure the majority of those downloads are coming from some downstream packages that everyone is using.

Ordering and showing dependent-downloads would be useful in security issues when wanting to contact package authors who have the largest exposure to an exploited package.

It was raised on npm’s feedback before, I don’t think they were interested in adding it.

EDIT: the bulk of downloads appear to be from handlebars-helpers

Click ‘Dependents’.
Dependents doesn’t order by download count though, you don’t know which of the 46 dependents are downloading it the most.
In this case main culprit seems to be a package called handlebars-helpers which is a collection of utilities for working with the handlebars templating language which was pretty popular in the JS world for a while.
Take a look at the author's github bio, the grift is pretty obvious:

> I've created more than 1,000 open source projects in an effort to reach my goal. Open source software takes a lot of time to create and maintain, and millions of projects now depend on my code.

This probably is most telling: "I switched careers from sales, marketing and consulting".

Having said which, if his intention was to use his skills in sales, marketing and consulting to achieve these results, he has certainly achieved it.

I don’t think the root logic it ultimately depends on is obvious: https://github.com/jonschlinkert/is-number/blob/master/index...

And so this is a perfect abstraction to make something non- obvious obvious.

The real question is why this shouldn’t be part of the interpreter?

Yes the dependency on isOdd is needless, but is a red herring.

Most commenters here didn’t look deep enough, sadly.

Hmmm, that's not what I'm seeing when all this is put together.

isOdd coerces to a number using Math.abs, so the string checks in isNumber don't apply.

    function isOdd(value) {
      const n = Math.abs(value);
      if (!isNumber(n)) {
        throw new TypeError('expected a number');
      }
      if (!Number.isInteger(n)) {
        throw new Error('expected an integer');
      }
      if (!Number.isSafeInteger(n)) {
        throw new Error('value exceeds maximum safe integer');
      }
      return (n % 2) === 1;
    }


    function isNumber(num) {
      if (typeof num === 'number') {
        return num - num === 0;
      }
      if (typeof num === 'string' && num.trim() !== '') {
        return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
      }
      return false;
    }
The problem here is not npm or the package itself.

The absurdity of 140k weekly downloads is a result of CI/CD practices.

I'm probably in the minority here but I think npm and github should actively disallow (or atleast discourage by making it very uncomfortable) to re-download the same dependencies from the internet on every pull request.

Judging from this page (https://www.npmjs.com/browse/depended/is-even), it appears that many of its dependents are joke packages. For example:

- is-is-even: checks if the passed function is is-even

- is-odd-or-even: determines if a given number is odd or even.

- is-ice-cream: Amazing lib to check if string contain your favorite ice cream flavor

Probably the main reason it has so many downloads is that it's imported as a module (rather than integrated as a constituent function) by the author's popular handlebars-helpers library of utility functions. Imagine if underscore.js were to separate out first() as its own module. Then you'd have a similar situation.

It's astonishing how many people defend a clear lack of basic math knowledge.
To be fair he says on GitHub:

i-voted-for-trump

This is a joke. You'll only see this org if you are attempting to troll me about repositories I created when I was learning to program.

is-odd

Public archive I created this in 2014, the year I learned how to program. All of the downloads are from an old version of https://github.com/micromatch/micromatch.

There must be some interesting edge cases with the idea of certain numbers being even or odd. I’m not familiar with whether the underlying numeric types can accomodate these values in JavaScript, but off the top of my head - what does maths have to say about the idea of the even/odd-ness of infinity, not-a-number, imaginary numbers. And there’s always undefined too. I suppose what I’m getting at is whether the answers to these questions are consistent between different packages and languages.