

Underscore.js: Functional Programming for jQuery - jashkenas
http://documentcloud.github.com/underscore/

======
simonw
Looks like a very handy bunch of code, but I can't say I like the "_" part of
it.

One of the neatest things about jQuery is the way all of the jQuery
functionality lives in the "jQuery" namespace, with $ just set up as a
convenient shortcut. If you don't want the $ in your global namespace (but
still want it in your own code) you can do this:

    
    
        jQuery.noConflict();
        jQuery(function($) {
            // Code that uses the $ shortcut
        }
    

Feature request for underscore: something similar. If I'm already using the _
for something I'd like to still be able to use the underscore library, but
bound to a different symbol.

    
    
        Underscore.noConflict();
        Underscore(function(_) {
            // My code that uses _
        }

~~~
jashkenas
Thanks for the suggestion, Simon -- It's done.

The Underscore page now has the download for version 0.1.1, with a noConflict
function that returns the "_" variable to its previous value.

    
    
        var myUnderscore = _.noConflict();

~~~
simonw
That's awesome! Thank you very much.

------
jashkenas
Quick Summary: Underscore provides all the functional programming goodies that
you would expect with Prototype.js or Ruby, but without extending any core
javascript objects, so it can fit hand-in-hand with jQuery. In Javascript 1.6
compliant browsers, it delegates to the native versions of functions, so you
can have your "map()" and run run it at native speed where available. The
production version compresses to 4k, so there's not much overhead in adding it
to a page.

Blog Announcement: [http://www.documentcloud.org/blog/2009/10/28/underscore-
dot-...](http://www.documentcloud.org/blog/2009/10/28/underscore-dot-js/)

Git Repo: <http://github.com/documentcloud/underscore>

Test and Benchmark Suite:
<http://documentcloud.github.com/underscore/test/test.html>

~~~
aristus
Awesome stuff but binding your library to _ (underscore) is unfortunate. That
character is traditionally reserved for the gettext / i18n / gimme-a-string-
in-human-language-X function.

    
    
        <h1>_('WELCOME_USER', user.firstName)</h1>
        <p>_('WELCOME_INTRO_TEXT')</p>
    

etc...

------
swannodette
Or if you're into MooTools checkout <http://github.com/ShiftSpace/functools>
for decorators, pre & postconditions, memoize, arrays and hashes as functions,
currying any function parameter, function composition, arity dispatch, etc.

Check out <http://github.com/ShiftSpace/promises> for bringing functional
sanity to AJAX requests as well support for lazy values:

    
    
      function example() {
        var remotes = ['a', 'b', 'c', 'd', 'e', 'f'];
        var result = "";
        while(remotev = remotes.shift()) {
          result = add(result, get(remotev)); // get is an async request! ;)
        }
        show(result); // -> console.logs "abcdef"
      }
    

No callbacks, your code looks like (and _is_) regular javascript even though
this triggers 6 requests. AJAX callback code is the new spaghetti and this is
an antidote.

And finally a <http://github.com/ShiftSpace/set> for a Set datastructure :)

~~~
osteele
Promises looks fun!

You might also be interested in
<http://osteele.com/sources/javascript/concurrent/> for another approach to
this. [later, after reading more:] Actually, Promises looks much more complete
and useful.

~~~
swannodette
Thanks for this! I recall reading over your article,
<http://osteele.com/sources/javascript/functional/>, back in the day and being
completely baffled and intrigued. These days I've been hacking with Clojure
and wanting to bring some of that FP sanity back to my daily work ;)

------
tlrobinson
What does this have to do with jQuery?

 _edit: by that I mean it's useful without jQuery. It's already been added to
Narwhal server-side JS package
manager:<http://github.com/kriskowal/underscore> _

------
jashkenas
Thanks to all your suggestions, Underscore 0.2.0 is out, with:

* "reduce" instead of "inject" (inject is now an alias).

* Other aliases added for Javascript 1.6+ standardized names (forEach, filter, every, some).

* "compose", and "lastIndexOf" added.

------
slig
Check also: <http://code.google.com/p/functional-javascript/>

It's not tied to jQuery and approaches things in a particular way.

~~~
jashkenas
Underscore isn't tied to jQuery either. It just complements it nicely.

Oliver Steele's Functional is a great library too, and bits of Underscore were
inspired by it. The main difference between the parts they have in common is
that Functional.js extends the core Function prototype, while Underscore
avoids altering any core objects.

~~~
osteele
Thanks! You can also feel free to mine <http://github.com/osteele/collections-
js>, which is a version with just the collection functions (but still modifies
built-in objects, so may not be to other people's taste), that I've been using
in conjunction with jQuery. I haven't finished looking over your library, so I
don't know if there's anything in there that would still be useful to you.
There's a set of unit tests, which might be.

I eventually found that I was accumulating so many string functions that, in a
version of this for OpenLaszlo here <http://github.com/osteele/lzosutils>, I
broke them into a separate file.

~~~
jashkenas
Collections-js looks like a nice split -- I might end up nabbing a few more
things out of there. Maybe some of the unit tests too, although, FYI, your
Functional.js page has shown "Documentation Failed to Load" for me for the
last few days (on Webkit).

One thing that it would be nice to agree on is the standard names for some of
these things under Javascript. What should reduce be called? Inject? Foldl?
I've followed the Prototype/Ruby naming conventions, but it might make sense
to provide all of the commonly-used aliases -- especially when you're not
extending core objects, and don't need to worry about cluttering them up. What
do you think? Does the same function under 5 different names run as sweet?

~~~
davidmathers
Not inject. Inject was borrowed from smalltalk's #inject:into, but dropped the
"into" and just ended up being unintuitive for many people. Ruby 1.8.7 and 1.9
now have #reduce, so I'd say that's the way to go. No reason to use foldl
unless you're going to also have a foldr.

~~~
jashkenas
Version 0.2, which should be out this evening, will call it "reduce", and
alias it to "inject". Thanks for the feedback.

------
cscotta
Thanks, jashkenas - this is fantastic.

I spend most of my day as a Ruby developer, but when I'm doing frontend work,
the thing I miss most in Javascript is Ruby's incredibly simple, powerful list
operations. While most of these have existed in some form for awhile now, I've
never seen such a comprehensive implementation in just 5.2kb (minified) of
very clean, simple, well-commented code.

This is probably going in every project I work on from here on out. Thanks for
putting all of this together.

------
axod

      >> _.first(array)
      >> "Convenience to return the first element of an array (identical to array[0])."
    

How is _.first(array) more convenient than array[0] ? :/

~~~
natrius
Sometimes you need a function. The alternative isn't array[0]; it's function
(array) { return array[0]; }.

~~~
axod
Ah thanks. Makes sense now.

------
dagw
I know I've implemented a fair few of those functions on a more ad hoc basis
in number of projects. So it's really nice to see someone putting it all
together in a simple package. I'll certainly be having a closer look at the
source code and trying it out on my current project.

------
futuremint
This will go great with jQuery. I've missed some of these helpers when moving
to jQuery from Prototype. I felt much better about not polluting globals after
the switch, but this look like it's a nice half-way solution between
Prototype's style and nothing at all.

------
jashkenas
0.3.0 is out, with a bunch of fine-tuning loop optimizations provided by
Dmitry Baranovskiy, and CommonJS/Narwhal support, for those of you who use
JavaScript on the server as well as the client.

------
warfangle
Cool stuff. The only thing that keeps me from writing in a more functional
style is the fact that no current browser implementations perform tail
recursion optimization.

------
subbu
Why not extend jQuery with all these functions? Then we can write things like:
jQuery.makeArray(document.getElementsByTagName("div")).inject(..)

~~~
mahmud
Because those of us who are _not_ going to use it shouldn't be burdened with
it.

cat jquery.js functional.js > myfatquery.js and be happy.

------
muxxa
see also: <http://mochikit.com/doc/html/MochiKit/Base.html>

------
hackworth
nice, all this needs is a Class object and it'd be perfect (though i guess you
could just add base.js to the mix).

~~~
jashkenas
Funny, that's precisely what we're doing at DocumentCloud -- Base.js for OOP /
jQuery.js for DOM and Ajax / Underscore.js for functional...

Part of the idea is to make it easy to add functional utility methods to an
existing project without making any other assumptions. You can use it with
whatever OO scheme you've got cooked up, any Ajax library, and any DOM-
manipulation framework.

~~~
nikz
What advantages would a "mix'n'match" approach like this have over something
unified like Prototype (which, as far as I can tell, includes implementations
of all the parts you are using)?

I have found Prototype much better for a "web-app" framework - I can build up
complex controls and effects with the "OOP"/Inheritance framework, and I have
access to all the functional tools I'm used to from Ruby.

JQuery, on the other hand, has always felt "lighter" - really great for a
quick Carousel control on a marketing site, or a pop-up effect or something
like that, but it quickly turns into spaghetti with anything more complex.

I'd be interested in other people's views on this split, especially people
with experience using a whole toolset like yourself.

