Mad, Beautiful Ideas
Upcoming YUI 3 Features: Collections

A new YUI module is being introduced in the next version of YUI3. I don't know for sure when it will be released, but the code is already up on Github, if you want to check it out now. The current member of the Collection object consists of a set of Array operations that were deemed useful enough to be in the library, but not common enough problems to justify being in the core YUI Array library. The extension consist of a few methods I wrote, and a set of array operations contributed by Gabe Moothart, which originated from Christian Romney's yui-functional package.

The functions being added are as follows:

  1. some: This used to exist the the core Array library, but has been moved to this Collection library. It will execute a given function on each element in an array until the enclosing function returns 'true'. This method will use the native implementation, if available.
  2. lastIndexOf: Similar to the wrapper on indexOf, this returns the lastIndexOf of a given element. It will use a native implementation, if available, and like the native implementation, it will not work when comparing objects. This was one of my contributions.
  3. unique: Returns a copy of an array to the caller with all the duplicate entries of an array removed. Like indexOf and lastIndexOf, this does not work on Objects. It takes an optional argument to determine whether it should sort the array or not. By default, it will sort the array. This function was contributed by myself.
  4. filter: Executes a filtering function on each element of an array, returning a new array containing only those elements for which the filtering function returns true. Will use a native implementation, if available.
  5. reject: Same as filter, but selects those elements for which the function returns false.
  6. every: Like some, but executes on all members of an array. Uses a native implementation, if available.
  7. map: Returns a new array containing the result of executing a given function on each element of the argument array. Will use a native implementation if available.
  8. reduce: Executes a function on each item in the array, ultimately folding the values into a single value. Will use a native implementation, if available.
  9. find: Like indexOf, but bases the return on the result of an argument function, allowing better control over what is returned.
  10. grep: Returns a new array of elements from the initial array which match the given regular expression.
  11. partition: Execute a function on each element of an array, returning a pair of arrays, one which contains matches, one which contains rejects from the method.
  12. zip: Takes two arrays, and returns a new array with members taking from each of the child elements.

Aside from the fact that some of my code was accepted (which is exciting for me in it's own right), there are some things in this which should be really useful. The ability to do Map-Reduce in JavaScript (regardless of native implementation) stands to be really useful. Aside from maybe the zip method, I can think of circumstances where I'd want to use just about every one of these methods. I'll be talking about Map-Reduce in a later post, but the wikipedia page (linked above) is a good place to start.

Using the collection module will be really easy, once it's released. If you're doing something where you need to pull only the unique entries out of an array, you'll just do this, which is an update I'll be making the Laconica widget on my sidebar.

        _uriLink: function(msg) {
            var Y = YUI().use("collection");
            var le = /([A-Za-z]+\:\/\/[^"\s\<\>]*[^.,;'">\:\s\<\>\)\]\!])/g;
            var r = msg.match(le), s = '$&', i;
            r = Y.Array.unique(r);
            for (i = 0 ; r && i < r.length ; i += 1) {
                le = new RegExp(r[i].replace('?','\\?'), 'g');
                msg = msg.replace(le,s);
            return msg;

This is necessary, because if I try to do a RegExp replace on a URI more than once, the output is completely hosed (as it should be). In the above code, I'm using the more traditional YUI usage, where my Y object is initialized to only the code I need. I could use the recommend syntax, where use() takes a function argument in which I use the YUI object, but that would be best done with a significant rewrite of the module, which is forthcoming.

I'm really happy with YUI up on GitHub, not only can we now easily follow what changes are coming down the pipe from Yahoo! it is now a lot easier to get changes integrated into the codebase. I suspect this will lead to more ancillary libraries like this one, which gather together useful functions which don't necessarily belong in the core of YUI, but certainly can be (and should be) easily added into any project which uses YUI. Now, I just need to get my tests checked in, and move onto other projects as I think of them.

Speaking of tests, if you use YUI, and don't have any ideas for code to contribute, start looking at writing tests. The test coverage on YUI3 could be better than it is, and that's an easy way to get started in contributing. Plus, it's a great way to familiarize yourself with YUITest, which I believe to be the best JavaScript test framework available today.