Underscore.js: how to chain custom functions

Using Underscore.js, I can write the following which returns 42:

_([42, 43]).chain()
    .first()
    .value()

I have custom function, not part of Underscore.js called double():

  • RxJS Promise Composition (passing data)
  • In Javascript, why is there no “prototype” property for an instance or object literal?
  • map function for objects (instead of arrays)
  • What Javascript libraries have good support for syntax highlighting of OCaml code?
  • Should Maybe.map respect the mapped value?
  • Lodash filter and functional composition
  • function double(value) { return value * 2; };
    

    I would like to be able to call this function in an Underscore chain, as if it was part of Underscore. I would like to write the following, which I’d like to return 84:

    _([42, 43]).chain()
        .first()
        .double()
        .value()
    

    This can’t work since Underscore doesn’t define double(). I could use tap() as in:

    _([42, 43]).chain()
        .first()
        .tap(double)
        .value()
    

    This is valid, but tap applies the function to its argument and returns the argument, not the result of the function. So it looks to me like I would need a sort of tap that returns the result of the function applied to its argument. Is there anything like this in Underscore.js? Am I missing something terribly obvious?

  • Different functions - are they the same?
  • Why does a Javascript function act differently upon instantiation than execution?
  • Handling double clicks AND single clicks gracefully with FRP and Bacon.js
  • Best way to get intersection of keys of two objects?
  • What is polymorphism in Javascript?
  • Why is immutability so important(or needed) in javascript?
  • 8 Solutions collect form web for “Underscore.js: how to chain custom functions”

    Not finding a tap that returns the value returns by the function is runs, I define one which I can take and add to _:

    _.mixin({take: function(obj, interceptor) {
        return interceptor(obj);
    }});
    

    Then assuming I have:

    function double(value) { return value * 2; };
    

    I can write:

    _([42, 43]).chain()
        .first()             // 42
        .take(double)        // Applies double to 42
        .value()             // 84
    

    You can look at take as map on objects, instead of lists. Want to experiment with this? See this example on jsFiddle.

    So you have a custom function:

    function double(value) { return value * 2; }
    

    You can use mixin to extend Underscore with it:

    _.mixin({ double:double });
    

    Now you can call your function from the Underscore object _:

    _.double(42); // 84
    

    and from the wrapped object returned from chain:

    _([42, 43]).chain()
      .first()
      .double() // double made it onto the wrapped object too
      .value(); // 84
    

    Alright, I’m fresh off of reading the underscore annotated source code for the first time. But I think you can do something like this:

    function double(value) { return value * 2; };
    
    var obj = _([42, 43]).addToWrapper({double:double});
    
    obj.chain()
      .first()
      .double()
      .value();
    

    The syntax/details might not be right, but the core point is this: when you call _([42,43]), you’re calling underscore as a function. When you do so, it instantiates a new object and then mixes into that object most of the underscore functions. Then, it returns that object to you. You can then add your own functions to that object, and none of this pollutes the “_” namespace itself.

    That’s what the underscore.js code looked like to me. If I’m wrong, I’d like to find out and hopefully someone will explain why.

    EDIT: I’ve actually been using underscore.js heavily for about a month now, and I have gotten pretty familiar with it. I now know it behaves like I said here. When you call _ as a Constructor function, you get back your own “namespace” (just an object), and you can add things to it with addToWrapper() that show up in your namespace but not in the “global” “_” namespace. So the feature the OP wanted is already built in. (And I have been really impressed with underscore, btw, it is very very nicely done).

    No one actually answered this as requested so here’s my answer to the request which I have tested.
    Please read the note below as regards first.

    function doubleValue(x) { return x * 2; }
    var rt = _.chain([42,43])
            .first(1)
            .map(doubleValue)
            .value();
    console.log(rt);   // prints out [84]
    

    // Note that it is important to tell .first() how many elements you want otherwise you may get an empty array otherwise. Think of first as I WANT the first number of items, so .first(2) returns [84],[86] etc

    Many ways to easily achieve this, here is one such solution:

      _.chain([42,43])
        .first(1)
        .map(double)
        .first()
        .value();
        // 84
    

    However, I would recommend using Ramda then with auto-curry and pipe / compose these kinds of tasks are trivial:

    R.pipe(R.head, R.multiply(2))([42, 43]);  // 84
    
    equivalent to:
    
    R.compose(R.multiply(2), R.head)([42, 43]);  // 84
    

    If you wanted to extend the solution to take say the first 2 items, instead of a single value, as requested by the OP, then:

    R.pipe(R.take(2), R.map(R.multiply(2)))([42, 43])  // [84, 86]
    

    However, in Ramda R.compose is preferred. Either way, for trivial tasks like this, it does tend to be more convenient and easy to use.

    Looks like lodash has implemented exactly what you are looking for:

    _.thru(value, interceptor)
    

    from the docs:

    This method is like _.tap except that it returns the result of
    interceptor

    https://lodash.com/docs#thru

    Does map work for this?

    _([42, 43]).chain()
        .first()
        .map(double)
        .value()
    

    edit

    from the documentation, it looks like map would only work if you place it before the call to first:

    _([42, 43]).chain()
        .map(double)
        .first()
        .value()
    

    Using compose is another way dealing with the situation, but I think adding a function such as take as I suggested earlier is a better solution. Still, here is how the code would look like with compose:

    function double(value) { return value * 2; };
    
    _.compose(
        double,
        _.first,
        _.bind(_.identity, _, [42, 43])
    )();
    

    The initial value needs to be provided through a function which returns that value (here done by currying identity), and the functions need to be listed in an other which is the reverse of what you have with a chain, which appears as pretty unnatural to me.