← Back to context

Comment by jperras

11 years ago

Similarly, the `average` package on NPM is one that I came across:

https://www.npmjs.com/package/average

    var average = require('average');
    var result = average([2, 5, 0, 1, 25, 7, 3, 0, 0, 10]);
 
    console.log('The average for all the values is:', result);

It's hard to not stare at that in complete disbelief; someone thought that it was worthwhile to create a package for determining the mean of an array of numbers.

You know what's worse? Javascript numbers are all floating point numbers, which means integers are 53 bits long. So, you might think this library would try to address issues this can cause, but nope, this is the average statement you'd write if you didn't know was a mantissa was and had never heard of big.js, bignumber.js, decimal.js, crunch.js or even strint (which represents integers as strings because wtf not).

  • Every once in a while, I come to HN, and inevitably find a post about some new JavaScript technology on the front page, wherein I find some comment that gives me a new appreciation for the web app language I use at work, which fortunately is not JavaScript.

    • What is the web app language you use at work? I assume you're talking about something that runs on the client -- a web browser -- so it probably compiles down to JavaScript, right? JS literally has no numeric type that isn't a float, so how does your language escape this fundamental limitation?

      12 replies →

  • That's not true. In most javascript implementations, integers will be represented by real 32 bit integers.

    • How does that help? Besides they overflow to doubles if they get bigger than 2^31-1 anyway.

      The problem with a naive average like this is that if you're averaging a bunch of big numbers there is a very high chance of overflow when you're summing, so even if all the numbers fit in 32 or 53 bits your calculation will be off.

      If you're not averaging thousands of large numbers, why are you even using a package instead of nums.reduce((a,b)=>a+b) / nums.length anyway?

    • Source? I find this very hard to believe. 1. How does the engine know of it should be an integer or not? 2. Why would they have a special case for this, it won't benefit accuracy and treating them in a special way probably hurts performance more than just always keeping it as doubles.

    • As long as everything used is really an integer and that everyone you work with is careful to keep things as ints (oring with 0 and such)

Well a bunch of standard libraries have sum defined, right?

JavaScript has suffered from a lack of a standard library for a while. Having a small package like this means that (in theory) everyone is using the same bug free version of summing instead of writing their own.

Honestly having JS start building a standard library at this point would be wonderful.

Sounds like the author was aiming for something to put on his resume: e.g., "Author of 25 libraries on NPM, some with more than 500K downloads." etc...

  • Well if I was interviewing the guy, my second or third question would be "tell me about these packages you published on NPM"

    It's going to be damn hard to make an average function sound impressive.

    • I think you're seriously overestimating quality of the average programmer candidate.

      Someone who understands what NPM is, has written and published working code (even stupid code) is miles ahead of the curve already.

      Most companies in the world, especially non-software companies, don't go for 5% hacker gurus. Attracting someone vaguely competent is already a blessing.

      1 reply →

    • In JavaScript, the API could be fairly complex. Thing is, JavaScript doesn't have arrays of numbers. So, what should the function do if the array passed in contains a null, an undefined, a string such as "7", "012", "008", or "2+3", a function, another array, a hash, etc?

      I can easily see this grow into a function accepting options indicating such things as "null values are zeroes", "ignore null values", "evaluate string arguments", etc, or maybe into a factory that produces customized averaging functions.

      For example, average([null,1,2,3],[4,5]) could either be 3 (the average of all numbers), 2.5 (sum of numbers divided by number of 'root' items), undefined (input format error), 3.25 (average of average of [1,2,3] and average of [4,5]), etc.

      And what if it gets passed arrays of equal size? "average([1,2,3],[7,4,5])" could easily be interpreted as a vector average, and produce [4,3,4]

      Silly? Yes, but if you want to write a robust library in JavaScript, you have to think about what to do with all these kinds of input.

      And of course, there are the simple variants of harmonic mean, arithmetic mean, and geometric mean, and several others (https://en.m.wikipedia.org/wiki/Average)

      5 replies →

    • Im of the mind most employers are looking for "have you done stuff" "can you do stuff". Veey rarely are they looking for anyone extraordinary, simply a tool that works

      1 reply →

  • That plus perhaps some kind of dopamine kick these people get out of this whole charade... Sindre Sorhus keeps describing himself as an "Open Source addict", after all.

This sounds like a symptom of an inadequate standard library. I do expect to be able to call "average" on a list of numbers without writing it myself, but I expect that to be part of the language not a 3rd party package.

  • > I do expect to be able to call "average" on a list of numbers without writing it myself

    Just out of interest, what kinds of functions would you expect to have to write yourself, if you're not happy about calculating the average of a list of numbers?

    • Alright, take a simple function like average. How might someone naively calculate the average?

          for n in list
              sum += n
          return sum / len(list)
      

      Which will fail but will probably be caught in the code review. Then a cleverer developer might think to write

         l = len(list)
         for n in list
            sum += n / l
         return sum
      

      Which will also fail but in more subtle ways, hopefully the senior dev will catch it in the code review.

      Then they correct it to

          l = len(list)
          for n in list
              sum += n / l
              rem += n % l
              sum += rem / l
              rem = rem % l
      
          return sum
      

      But this could further optimized and might still be dangerous. This one might not be fixed at all in the code review.

      The best algorithm might be Knuth's which is fairly non-trivial and might not even be the fastest/most efficient given certain unique JS optimizations.

      Do you want to do this for every 'trivial' function or would you rather import average where (in theory) someone knowledgeable has already done this work and benchmarks for you and you get the best performing algorithm basically for free?

      6 replies →

    • Those that are unique to the problem I'm actually trying to solve, and not already in the standard libraries or well-maintained packages of mainstream languages.

      6 replies →

  • It should, but the ECMAScript spec doesn't have it, and Node.js team prefers to keep the core libraries to a minimum and definitely do not want to modify prototypes. Thus we depend on userland to provide those features for us.

I'm thinking that someone wanted to learn about building and publishing a package and the ecosystem so they made this computationally trivial thing as a practical exercise.

Pretty much every package management system gets cruft in it like this. Example: for a long time someone had uploaded a random Wordpress core install into Bower.

And 54 people found it a worthwhile package to install _this week alone_.

  • That could be one dependent module that got installed in 54 places. More likely, it was mostly various bots that install everything on some semi-regular schedule.

Yes, but it's MIT licensed. We also need average_GPL to go with it.

  • You bring up a good point with respect to copyright/licensing --- at what point does code stop being copyrightable and become public domain simply due to pure triviality? There are not very many sane ways to write an averaging function, and the most straightforward one (add up all the value, then divide) would probably be present in tons of other codebases.