Settings

Theme

Lodash v3.0.0

lodash.com

245 points by gitspirit 11 years ago · 81 comments

Reader

astalwick 11 years ago

We switched from underscore to lodash several months ago, and haven't regretted it. The fact that lodash follows semver is huge. Underscore has introduced serious breaking changes in minor point-releases more than once, which is completely unacceptable for a utility library.

  • untog 11 years ago

    Semver isn't a requirement nor be-all-end-all, though.

    • cmpb 11 years ago

      It is, however, amazingly convenient and capable of saving a lot of time in bug fixes.

    • coldtea 11 years ago

      Isn't what's a "requirement" something that THEY get to decide for their code base?

allendoerfer 11 years ago

  The lodash & lodash-compat npm packages now come with modules baked in too.
  Perfect for Browserify!

  // load the modern build
  var _ = require('lodash');
  // or a method category
  var array = require('lodash/array');
  // or a method
  var chunk = require('lodash/array/chunk');

This is great. It combines trust and quality with modularity.
tobr 11 years ago

Really nice to see that there's now an auto-curried, function-first version, lodash-fp! I've been really attracted by Ramda JS recently for this reason.

https://www.npmjs.com/package/lodash-fp

  • rikkus 11 years ago

    I've been looking for some real-world examples of how currying might be useful in javascript. Haven't not used a language which supports currying for any real world project, I'm interested to know how it can help.

    I found a page [1] which talks about currying in javascript, then says "Are there practical uses for currying in JavaScript? Not really."

    Can you point me at anything which will help me see why it's useful?

    [1] http://benalman.com/news/2012/09/partial-application-in-java...

    • ilitirit 11 years ago

      Some code that I've written using Ramda.js:

        var predicateListFunc = function(props) { return R.allPredicates(R.map(R.curry(R.eqProps), props)); }
        var compareProperties = R.unapply(predicateListFunc);
      
        var mergeLists = R.unionWith(compareProperties("Property1", "Property2"));
        var groupById = R.groupBy(R.prop("Property1"));
        var getGroups = R.compose(R.toPairs, groupById, mergeLists);
      
        var groups = getGroups(list1, list2);
      
      
      With this code I can merge any two lists (list1 and list2) on any two properties (Property1 and Property2), and then group the result. I use this to synchronize client and server data.

      I don't know if this answers your question, since I wrote in about an hour of learning Ramda.js, and there might be an easier way of doing it.

      Here's a fiddle:

      http://jsfiddle.net/Gk6uu/10/

    • albertkawmi 11 years ago

      This slideshow [1] by one of the authors of Ramda.js goes over a JavaScript example in OO style and refactors it to functional style. Currying is used to complete the refactoring.

      I've linked to the slides on currying but you'll need to back up to follow the whole example.

      [1] http://scott.sauyet.com/Javascript/Talk/FunctionalProgrammin...

      • drapper 11 years ago

        Wow, thanks, that presentation is pure gold! The best thing about FP (and moving into it from the OOP world) I've ever seen: clear, easy to follow, based on a practical example and really presenting the sense behind the use of FP.

    • wizao 11 years ago

      There is an excellent talk called "Underscore, you're doing it wrong!". The talk explains how well designed param order with currying leads to very short and expressive code -- and how underscore missed the boat. This aspect of it should be interesting as it's related to this post. It's well worth the watch.

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

      • WickyNilliams 11 years ago

        I was just about to post exactly this. Well worth a watch. It was this talk which finally made currying "click" for me. And serendipitously the topic is the improvements currying and swapping args can make to the underscore (or lodash!) API.

        I even tweeted to @jdalton on announcement "hey lodash, you're doing it right" :)

    • ufo 11 years ago

      One situation where I felt compelled to use lots of currying was when I was working with a promise library for async code. There are lots of little callbacks you need to use and you benefit from having combinators that act as function versions of js operators, like "+", "[]" and so on and currying helps cut down on the number of combinators you need.

      That said, I didn't end up being a big fan of it in the end. Other people can get confused by the new abstractions the combinators introduce and whenever you pass the wrong number of arguments to a function you end up with very tricky runtime errors (this isn't an issue in Haskell because the type system checks this for you)

      • Lio 11 years ago

        That sounds like an interesting approach.

        Would mind posting an example?

        (I was wondering what something like Flow.js would make of the code. i.e. Could it make catching those errors easier)

        Cheers.

        • ufo 11 years ago

          Its been a while since I worked with this so this is kind of a shitty example out of the top of my head:

          If you have code that looks like this:

              var user_list =
                 fetch_json()
                 .then(function(data){
                     return data.users
                 })
          
          You can write it more succinctly using a combinator library instead of writing the callback out by hand:

             var user_list =
                 fetch_json()
                 .then(get('users'))
          
          Similar things also apply on other code that uses callbacks like maps, filters, etc. I also had combinators for other common JS operators (set, "+", "==", ...)

          The point where currying comes in is that it lets you define a single "get" function instead of a separate versions for one and two arguments:

              //curried
              x = get('users', data)
              y = get('users')(data)
          
              //non curried
              x = get2('users', data)
              y = get1('users')(data)
          
          That said, there are some downsides to using combinators instead of writing the callbacks by hand. If you need to debug something the stack traces are harder to follow and currying doesn't play nice with functions like Array.prototype.forEach that pass "extra" parameters to the callbacks.

          In the end the feeling I got was that trying to make JS more functional is not worth the trouble. If I could go back I would try to replace the promises with something less intrusive in terms of coding style, such as generators/coroutines.

          • Lio 11 years ago

            Ah, I see.

            Yes, I think I've come to the exactly same conclusions in the past, both with regard to promises and curried (or partially applied functions for that matter).

            This may only apply to me but I've found that without strong, static typing to help out, my brain starts to melt sometimes trying to workout what heavily curried JS functions actual do without using a debugger.

    • jmcmichael 11 years ago

      "A programmer’s pipe-dream is to write code, and be able to use it repeatedly with little effort. It’s expressive because you write in a way that expresses what is needed, and it’s reuse because.. well, you’re reusing. What more could you want? Curry can help.":

      http://hughfdjackson.com/javascript/why-curry-helps/

    • woah 11 years ago

      It makes the syntax a bit better for combining functions. Seems like a small thing, but with all the complaining about nested callbacks I guess it's good. See Ramda, who came up with this concept, for a deeper discussion of the benefits.

      http://fr.umio.us/why-ramda/

    • findjashua 11 years ago

      Coming from a Python background, Ramda's (function, iterable) feels way more natural than vice-versa:

      https://docs.python.org/2/library/functions.html#map

olivierkaisin 11 years ago

See release notes and changelog: - https://github.com/lodash/lodash/releases/tag/3.0.0 - https://github.com/lodash/lodash/wiki/Changelog

  • bsimpson 11 years ago

    I dig laziness, but why is `forEach` lazy? That's the only one that invokes immediately in libraries like Lazy.js.

    • quadratini 11 years ago

      It's only lazy if it's part of a chain

    • jdd 11 years ago

      Chaining is deferred until `value()` is implicitly or explicitly called. However shortcut fusion does not apply to `forEach`.

  • riquito 11 years ago

    Thanks for the link, I was expecting a CHANGELOG file in the project.

Sarien 11 years ago

Q: "What does it do?"

A: "A utility library delivering consistency, modularity, performance, & extras."

Q: "Yeah, but what does it do?"

A: "Oh, nothing but it does it consistently, modularly and performant. We also have functions for string handling in the extras module."

  • nailer 11 years ago

    It's extra stuff that should be in the standard library but isn't.

    These days, a lot of it is actually in the standard library - for example, array maps - and invoking lodash just calls the es5/es6 built in, with a slightly uglier syntax.

    • acjohnson55 11 years ago

      But if you want backward compatibility, you still probably want to use something like Lodash. I'd also argue that Lodash's/Underscore's interface is far better thought out than the standard library. The standard library has so many absurd gotchas, like `["2", "2", "2", "2"].map(parseInt)`. The verbosity of Javascripts lambdas also makes composition of simple parts more arcane looking than necessary, and having a whole bunch of composable/chainable utility functions does a lot to help people write self-documenting code.

      • nailer 11 years ago

        > But if you want backward compatibility, you still probably want to use something like Lodash.

        A few years ago, sure, but these days I'd use es6-shim. The code will be shorter, have more documentation around the internet, and when old browsers die you won't have to change anything to be on standard JS.

        • jdd 11 years ago

          lodash offers features and performance over es5/6 built-ins.

    • ben336 11 years ago

      Interestingly, in practice lo-dash actually doesn't proxy through to the native implementation for things like map and forEach. Just using loops ends up being more performant because of some edge cases in the ES5 spec for those methods that lo-dash and underscore don't follow.

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

    • aliem 11 years ago

      The most important feature is chaining and lazy evaluation.

      I think the most useful functions are the typechecking utilities (typeof in javascript is the most useless keyword the human kind engineered in a language).

      In the end is a very nice library to work with when it does not get in the way (of course, if you are using `_.each([], fn)`, you should think again and use `Array#forEach` or a nice `for`)

      • M2Ys4U 11 years ago

        >of course, if you are using `_.each([], fn)`, you should think again and use `Array#forEach` or a nice `for`

        You probably shouldn't if you're in a hot path. LoDash actually outperforms some native ES5 features, Array#forEach being one of them IIRC.

    • _greim_ 11 years ago

      It should start being called "the jQuery effect" since it's one of those libraries that comes to be considered by the community as a standard way to patch the environment. Not only that, but some people begin to develop very strong, quirky aesthetic preferences for seeing it in their code.

  • laichzeit0 11 years ago

    I also had no idea what this was until I got to the bottom of the page. Looks like a "better underscore.js". They should just say something to that effect upfront.

    • codereflection 11 years ago

      They used too say that when the project was new. Perhaps now they feel the project is established enough that it can stand on it's own without trying to position it as a drop-in replacement for underscore.

Elrac 11 years ago

I followed the link and saw "lodash" for the first time today. Oh, it's a library! With an API! In various formats!

I always appreciate it when the top of the project page provides a one-liner explaining just what it is I'm looking at.

  • falcolas 11 years ago

    I wish that it had mentioned what it was a library for. Took me longer than it should have to identify that it was a Javascript library.

    I probably should have guessed, but I hate guessing wrong and missing out on something I could really use.

  • aikah 11 years ago

    Yeah,the doc sucks a bit because you're supposed to know it's a "fork" of underscore. They could do a better job at explaining why lodash is useful, because it definetly is.It can really reduce the amount of js code one is writing by 2 or 3.

    In a nutshell it's a collection of functions that work on arrays,objects and functions.It's a toolbox.

  • listic 11 years ago

    Yep, one might think that one could manage a decent description by version 3.0.0

  • jdd 11 years ago

    lol, added "JavaScript" to the description :)

acjohnson55 11 years ago

Lodash is an incredible accomplishment, and having it vastly improves the Javascript authorship process over the standard library.

That being said, I still can't believe we don't have a flatMap:

https://github.com/lodash/lodash/issues/812 https://github.com/jashkenas/underscore/issues/452 (Underscore repo, but still Mr. Dalton, author of Lodash, opposing.)

  • invisible 11 years ago

    He explained how to add a flatMap in 2 lines in the first linked issue. It sounds pretty trivial to add per app.

urza 11 years ago

It is alternative to underscore.js? Or extensions for underscore.js? Not clear from the page...

  • woah 11 years ago

    It's supposed to be better, faster, and stronger (more functions) than underscore.

    It's also under active maintenance from an enthusiastic dev. Do your own research, but I go with lodash.

sgrove 11 years ago

I've been playing around with getting Mori[0] more js-like, from more idiomatic function names and argument order (fn as the last argument, released) to playing around with a chaining API. Ideally we should be able to wrap javascript values, manipulate via idiomatic chaining (similar to Lodash), while getting most of the benefits from highly-tuned persistent data structures, lazy sequences, etc.

e.g.

    expect(_([1,1,1,1,2,2,3,4,5,6,6]).distinct().conj(7).out()).toEqual([1,2,3,4,5,6,7]);

Here's a small set of specs showing early ideas https://github.com/swannodette/mori/blob/8e82b15b35b2989d4a2...

[0] https://github.com/swannodette/mori

andrezsanchez 11 years ago

I've tended to avoid both underscore and lodash because they're both in the slew of monolithic pre-npm libraries, however the lazy evaluation looks interesting. I wouldn't be surprised to find a library that handles lazy eval without all the extra features Lodash brings.

  • jgalt212 11 years ago

    For the shops who don't live and breath js and whose js work is almost entirely browser-based, these monoliths are great. I, for one, am bummed that the js market is moving away from monoliths. e.g. YUI shutting down.

    • andrezsanchez 11 years ago

      That's an interesting perspective. I don't have any inherent problems with large libraries, but my problem with some of these 'monoliths' is that other libraries start to depend on the entire library when they only need a small piece of functionality that the library provides.

      Substack wrote an article [1] explaining some of the problems that monolithic libraries cause in an ecosystem.

      [1] http://substack.net/many_things

  • WickyNilliams 11 years ago

    With browserify (or webpack) you can require just the functions you want, and only those (and their dependencies) end up in your code base. This is covered in the changelog

  • acjohnson55 11 years ago

    There is lazy.js (http://danieltao.com/lazy.js/). Also, lodash is highly factored into pieces if you don't want the whole thing.

  • jdd 11 years ago

    lodash offers modules for node, es6, amd, individual npm packages and bundled in the primary npm package so you can even do require('lodash/array/chunk').

    • andrezsanchez 11 years ago

      I remember trying this a while ago and being disappointed at the amount of dependency code brought in for a rather trivial function, but the modularization is looking much better than it was last time I took a look.

jtheory 11 years ago

Whoah: "Tested in Chrome 39-40, Firefox 34-35, IE 6-11, Opera 25-26, Safari 5-8"...

IE6+ support! I wonder if that's real, full support, or more like a "there are serious bugs we'll probably never fix for old IE".

Working with old IE versions is loathsome (but still required for some of us), so libraries that just work there are much appreciated.

edwardg 11 years ago

For anyone interested in learning more about lodash, Adam Boduch's "Lodash Essentials" book just got released, and covers everything in v3 (he delayed it to make sure it covered v3).

https://www.packtpub.com/web-development/lo-dash-essentials

ecaron 11 years ago

The changelog at https://github.com/lodash/lodash/wiki/Changelog gives some nice examples of breaking changes for anyone moving from v2.x

sosuke 11 years ago

So going modern means breaking in PhantomJS, that is a bummer.

  • jdd 11 years ago

    It doesn't mean it's breaking in PhantomJS. The modern build lacks some iteration fixes for older environments is all. In the case of PhantomJS it's edge iteration of things like `arguments` objects. The modern build won't error out even in IE6.

tieTYT 11 years ago

It's not clear to me: Is that list at the bottom new things in v.3?

picardo 11 years ago

Is there build of this that lets me require a single function?

facepalm 11 years ago

Is this the same as underscore.js?

  • msl09 11 years ago
    • facepalm 11 years ago

      Thanks - it sounds as if you could use it as a drop in replacement for underscore.

      • Pephers 11 years ago

        Yes, you can. I've successfully done so in a Backbone/React app.

        The _.chain() method furthermore gives a nice functional style ways of building lists which is useful when building UI in React, like so:

            var list = _.chain([1, 2, 3, 4, 5])
                .filter(function (value) {
                    return value > 2;
                })
                .map(function (value) {
                    return value;
                });
        
            console.log(list);
        
            // prints:
            // [3, 4, 5]
        • masklinn 11 years ago

          That's not "furthermore". chain/value also exists in underscore.

          Also your code was broken in Lodash 2 (it'd return a lodash object, not a list) and is more broken in Lodash 3 (chains are now lazy), so your code does just about nothing until you force the iterator's evaluation)

          • jdd 11 years ago

            lodash v2 offers an Underscore build that aligns its chaining and other API with Underscore providing a full drop-in replacement. However because lodash is a superset of Underscore those using the Underscore build lose out on additional methods, optimizations, & cross environment fixes.

            Over the last year Underscore has align more & more with lodash’s API so the need for a separate Underscore build has diminished. If you still need compatibility around some of the edges you should leverage modules in lodash v3 to supplement your Underscore use until the time you can drop Underscore completely.

mackwic 11 years ago

Already submitted: https://hn.algolia.com/?query=lodash&sort=byPopularity&prefi...

Seems like no one cares. Strange.

  • Turing_Machine 11 years ago

    It's easy to not care when there's no context or indication as to what Lodash might be. Too many links, not enough time.

    I did click -- but only because a previous comment made it seem like Lodash was something related to functional programming. If it hadn't been for that comment, I have ignored the post, because I wouldn't have had a clue WTH Lodash was.

    Now, sure, people who've already used or heard of Lodash are going to know, but they're probably already following it on Github. :-) The unwashed masses like me won't have any idea.

    I guess the key here is to try to make the title give some indication of what the thing is.

    • weavie 11 years ago

      There are two kinds of JS developers, those that use LoDash at least once per function and those that have never heard of it!

  • arcatek 11 years ago

    I use Lodash but i see not point in this announcement in its current form - what changed exactly?

    [edit] Changelog is there https://github.com/lodash/lodash/wiki/Changelog

    Some decisions sound really weird, such as the fact that forEach is now lazy. It is not a standard replacement anymore, and probably break the compatibility for quite a few apps (even if I'm deeply convinced that we should all use the native functions and shim them when needed).

    • jkrems 11 years ago

      It's only lazy when using the chaining syntax - and that one was never a standard replacement since `_.map(arr, fn)` returns a wrapper around a value and not a value.

    • woah 11 years ago

      Are you talking about this?

          // in 2.4.1
          _([1, 2, 3]).forEach(function(n) { console.log(n); });
          // => logs each value from left to right and returns the lodash wrapper
      
          // in 3.0.0
          _([1, 2, 3]).forEach(function(n) { console.log(n); });
          // => returns the lodash wrapper without logging until `value` is called
          _([1, 2, 3]).forEach(function(n) { console.log(n); }).value();
          // => logs each value from left to right and returns the array
      
      Seems that the only apps this change will break are those who are using side effects in a chain. Which is a pretty dubious choice, IMO. Especially given that Lodash is a "functional programming library".

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection