Hacker News new | past | comments | ask | show | jobs | submit login
101 – A JavaScript utility library (github.com/tjmehta)
120 points by tjmehta on Nov 24, 2014 | hide | past | favorite | 46 comments



This is a nice start towards something that might be useful. A few thoughts about stating that "101 will be maintained to minimize overlap with vanilla JS." though:

1. Lo-Dash and Underscore overlap with ES5 for a few reasons. First, it allows them to support environments where ES5 functions aren't available. Those are becoming less common but still exist. But the other big reason they overlap is that Underscore and Lo-Dash both outperform native functional methods by a significant amount. Unintuitive but true, see my comparison from a few weeks ago [0]

2. It's worth thinking about who this library is for. The support for common JS and highly modular nature of the library make it seem like it is focused on Node first. But the value in a smaller library becomes much more clear in the browser where page weight matters.

These aren't meant as criticisms, it's good to see new ideas. But it's worth thinking about what niche you're filling when you develop a library like this.

[0]: http://benmccormick.org/2014/11/12/underscore-vs-lodash/


Love your well thought out feedback. 1) IMO ES5 is highly available now and when it isn't you can use shims. 2) Will definitely add other module systems on request. Currently works in the browser with browserify.


Isomorphic JS is only going to get bigger. Writing browser-friendly modules in CommonJS is an admirable strategy, especially since you're trying to avoid requiring your own custom build system.

I use Webpack (similar to Browserify, but I understand Webpack's more powerful), and I can't imagine starting a new JS project without it.


The proliferation of the term "isomorphic javascript" really has to stop.


But, the ISOs! Biodigital jazz, man!

https://www.youtube.com/watch?v=XEuLWKBSRqw.


The significant performance difference is usually only noticeable at very large objects/arrays.

A good read on the subject of performance and native method replacements:

https://github.com/codemix/fast.js/tree/master#how


There's another benefit to including map/reduce/filter in Lo-Dash and Underscore, and that is chaining. Were these methods removed in favor of native methods, _.chain would be much less useful.


I'm curious, what's the rationale behind

    var and = require("101/and"),
        apply = require("101/apply");
versus something like

    var o = require("101");
    
    o.apply(/*...*/);
    o.and(/*...*/);
I can see the first one works well if you're planning to use a couple of those functions at a time. If you end up using 4-5 of them in the same module it could get a bit much.


If you use something like Browserify only the code you require is added to the bundle it generates.


That makes perfect sense, thanks!


It's a great project to teach yourself something but I don't really see why people might want to use this over lodash/underscore?

For example, `exists` function can not really help with undeclared variables. At the end of day you have to use `typeof something !== 'undefined'`. I don't really understand what this library is trying to solve


Can we just stop with these kind of kitchen sink libraries?

I think substack said it best (https://github.com/substack/browserify-handbook#module-philo...):

People used to think that exporting a bunch of handy utility-style things would be the main way that programmers would consume code because that is the primary way of exporting and importing code on most other platforms and indeed still persists even on npm.

However, this kitchen-sink mentality toward including a bunch of thematically-related but separable functionality into a single package appears to be an artifact for the difficulty of publishing and discovery in a pre-github, pre-npm era.

There are two other big problems with modules that try to export a bunch of functionality all in one place under the auspices of convenience: demarcation turf wars and finding which modules do what.

Packages that are grab-bags of features waste a ton of time policing boundaries about which new features belong and don't belong. There is no clear natural boundary of the problem domain in this kind of package about what the scope is, it's all somebody's smug opinion.

Node, npm, and browserify are not that. They are avowedly ala-carte, participatory, and would rather celebrate disagreement and the dizzying proliferation of new ideas and approaches than try to clamp down in the name of conformity, standards, or "best practices".

Nobody who needs to do gaussian blur ever thinks "hmm I guess I'll start checking generic mathematics, statistics, image processing, and utility libraries to see which one has gaussian blur in it. Was it stats2 or image-pack-utils or maths-extra or maybe underscore has that one?" No. None of this. Stop it. They npm search gaussian and they immediately see ndarray-gaussian-filter and it does exactly what they want and then they continue on with their actual problem instead of getting lost in the weeds of somebody's neglected grand utility fiefdom.


That's a convincing argument, though there's also value in having a set of utilities that are maintained competently by someone you can have confidence in – I know that the functions in underscore, lodash, etc. are (at least mostly) bug-free and fast, whereas it's a hassle to evaluate the quality of every microlibrary I come across.


Depends on the case, for application-level development these aggregate libraries can be really handy, no one wants a stack of ~100 requires (I've seen it).


I totally agree with this philosophy. It sounds especially great on paper. However, while in practice, adherence to the module pattern can become quite annoying for very small modules. Small modules usage throughout a project can change very quickly, because of this one may find themselves repeatedly adding a removing utility modules at a multiple times a day. Small breaks to npm install or remove small modules throughout your day can lead to a lot of wasted time (since it breaks your programming focus). Also, remembering which small module you used can be difficult (bc there may be many). I think there are pro's and con's to each strategy.. IMO I think the micro libraries are an exception to the rule, where grouping them together can be beneficial to developers.


Indeed, 101 is broken up into an almost ridiculous number of tiny pieces -- the implementation of the and function is about as big as the necessary require statement. I think or() and and() (for instance) could be in the same file.


Disagree, is it very likely that `and` and `or` will always be used when either is required?


Um, yes.

Is it worth fine-graining libraries to the point where you're doubling the code required for almost every call?


This isn't a kitchen sink library. It provides syntactical operators as functions, much like the python "operator" module in the stdlib.


How would I use a "functional version of ||", or a "functional of &&"? I am not familiar with functional programing but maybe a short example of .or and .and would enlighten me a bit?


I'm guessing because .and is a function it can be used to pass into any higher order function.

    var x = [true, false, true, false];
    x.reduce(and, true); // == false
    x.reduce(or, false); // == true


that makes sense actually. Thanks!


> 101 will be maintained to minimize overlap with vanilla JS.

I'm confused, the majority of this library seems to be wrapper functions for built-in vanilla js operations.


Was waiting for someone to say this. Checkout the examples - duplication is for functional usage only. Util methods are written to work well with JS internals like Array methods (eg. map). I should probably make this point more clear in the docs... Thanks!


Just a note: the NPM manifest declares the entry point as "index.js", but this file does not exist.


Hey, thanks. Yah I kind've knew about this, and never got back to it. What do you think I should put in index.js?

I was thinking `throw new Error('You're doing it wrong');` :-P


In that case, it makes more sense to publish each submodule as an individual NPM module.


Further, it's worth putting the components on npm individually and retaining 101, but making it depend on those modules (so it's really just a wrapper). This is what lodash should do imo. Lodash has the separate bits on npm, but lodash itself does not depend on them, which is a little weird.


I like this idea - just would be really annoying to maintain each module as a versioned dependency...


I definitely did that for a while, but eventually found it annoying. I know it's definitely better to package each of these as a separate module. But uses of each of the tiny modules like these can come and go very quickly and keeping the package.json up to date becomes tedious..


That's where a build system comes into place. I noticed you don't seem to be using Grunt or Gulp which could really cut down on the maintenance.


You could stick it in /dist/index.js.

You could also make /dist/index.min.js.


var and = require('101/and');

and(true, false); // false

and(true, true); // true

I'm not convinced that there's a real need for that. Anyone else have a good use for something like that? Looks like it doesn't even take more than two arguments


I'm not convinced either. But for what it's worth, the tests for and() and or() essentially treat them as some() and all() using reduce()

https://github.com/tjmehta/101/blob/master/test/test-and.js


Providing an function version of `&&` let's you use that function in more FP (functional programming) contexts, e.g. a data transform that does multiple map/apply/reduce transforms to a data set.


A silly example:

  var Promise = require('bluebird');
  var fs = Promise.promisifyAll(require('fs'));
  var and = require('101/and');
  
  var paths = [...];
  Promise.map(paths, fs.existsAsync).reduce(and)
    .then(function(allExist) {
      if (allExist) console.log('all paths exist');
    });


FYI to the OP: in README.md, the example usage of apply() is the example from and().


Thanks fixed.


I really don't understand why anyone would want to use this.


Add new String(...) and new Boolean(...) to the is-(boolean|object|string) test cases for surprising fun, OP, then check out Object.prototype.toString.call(...).


how is this different from underscore/lo-dash other than the ability to include only the functions you want?


If you take a look on Github, the project explains that it intends to trim itself over time to reduce overlap with native JS functionality.


Does this work in the browser?


Yes, with Browserify.


Do I care about some bytes?


If you're writing mobile apps in developing countries, then yes absolutely.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: