This Week in JavaScript - 14 October 2013

This is a weekly update of some interesting things relating to JavaScript, to help encourage discussion and to bring some potentially new ideas to the fore.

Here’s what we’ve seen of interest this week.

Techniques

Making a Simple Game in JavaScript Step-By-Step - a video talk that takes you through the basics of creating a game

Searching using Array.prototype.reduce - with last weeks JavaScript under pressure, this reduce function became quite handy

Libraries

Lightweight URL argument and parameter parser - retrieve querystring and hash tag information with ease

FullCalendar - an open source event calendar from MIT with drag & drop, and is compatible with google calendar

Advanced

Currying in Javascript - do you need to handle functions that can be only partially evaluated?

Maintainable Automated UI Tests - removing brittleness from difficult to maintain UI tests

Frameworks

jsdb.io - definitive source of the best JavaScript frameworks, plugins, and tools

Getting MEAN - A boilerplate Mongo, Express, Angular, and Node stack for appllication development

The lighter side

Full Screen Mario

Take a look at these recent happenings in JavaScript, let us know what you think about them, and we’ll have some more to inspire you next week.

Feel free to PM me or [URL=“http://www.sitepoint.com/forums/private.php?do=newpm&u=184222”]PM Pullo if you have anything interesting for the next issue.

Hehe, that game is hilarious. :smiley:

For a better understanding of functional programming patterns, it should be mentioned that the solution for javascript under pressure #4 requires a filter not a reduce, or a fold how it is also called.

A filter will permit to return all the values that satisfy a certain criteria, while reduce is used to build up a final value. I’ve contacted UsVsTh3m on the matter and they’ve actually confirmed the test cases are lacking:

That’s true; I deliberately didn’t include that test case because it seemed a bit too much to ask of novice programmers.

Second that. I’ve just wasted an hour remembering what fun Mario used to be.

So I’m reading the article Searching using Array.prototype.reduce and I’ve run into a little challenge that the author has set.

entries = Array.apply(0, Array(entries.length)).map(function () {
  return entries.splice(findLongest(entries).index, 1).pop();
});

To give a little more context, my code looks like this:

var strings = ["aa", "b", "cccc", "ddd"];

function findLongest(entries) {
  return entries.reduce(function (longest, entry, index) {
    return entry.length > longest.value.length ?
      { index: index, value: entry } : longest;
  }, { index: -1, value: '' });
}

var sortedStrings = Array.apply(0, Array(strings.length)).map(function () {
  return strings.splice(findLongest(strings).index, 1).pop();
});

console.log(sortedStrings);

Would it be correct to say that in the above code (my version), the following is true:

In the callback function passed to .map(), we are removing the longest element from the strings array (using splice) and inserting it it into the corresponding element of the sortedStrings array.
We need to call .pop() as splice returns an array containing the removed elements.

Is there any reason for the use of .splice() or .pop() that I have missed?

I take many issues with what Ariya Hidayat writes. I’ve only read two of its posts, but it looks inadvisable. But later about this.

The “secret” is not with splice or pop, the “secret” is with Array.apply(0, Array(strings.length)). With that, he’s trying to build ahead an array with an exact number of “blank” elements in it: the length of strings. Then, he uses split and pop to “fill in the blanks”.

Now back to my issues. He’s oblivious to many things and misinformed on many others. The technique he describes for creating an array with a known number of “blank” elements without using a loop belongs to another post of his: http://ariya.ofilabs.com/2013/07/sequences-using-javascript-array.html, where he tries to convince me that Array(3) doesn’t produce [undefined, undefined, undefined] but… holes:


Array(3);                  // [,,,]
Array.apply(0, Array(3));  // [undefined, undefined, undefined]

The whole premise is wrong, in Javascript anything undeclared is undefined. He’s confusing array display (C’s printf analogy) with actual array values. Anecdotally, there are three commas for Array(3) representation, which suggest a return array of length 4, not 3.

The programming style is wrong in many ways: not caching variables in the for statement, not caching object properties he uses, obscure and unclear "apply"cations and so on, all in the name of a functional programming design he clearly doesn’t control.

You can take this as a vent, but it’s not. The guy just needs some more self time before posting functional programming Javascript blog posts.

Anyway, I should also post some code. It’s only fair that I expose myself to the same criticism I render. For a reduce only solution that returns: the longest length, longest strings and their respective indeces


var test = ["a", 0, "aa", 1, "two", 3,  "zero", "one", "four", "five", 6],
    longestStrings = [];


var returnValue = test.reduce(
    function(initialValue, currentValue, index){

        var max           = initialValue,
            currentLength = currentValue.length;

        if (currentLength >= max) {

            if (currentLength > max) {
                max = currentLength;
                longestStrings.length = 0;
            };

            longestStrings.push({"string": currentValue, "index": index});
        };

        return max;
    }
, 0);

console.log("max length: ", returnValue);
console.log("longest elements: ", longestStrings);


But, like I said, from a functional programming pattern point of view, the solution to the longest strings, and I repeat this, strings, not string, is a filter.

A reduce has its place here. It will be used to build up a final value: maximum string length. Then, a filter based on this maximum length is applied to the initial array. These are the expected uses for reduce and filter. Of course, one can jump the gun and solve the problem with just reduce, or take any other path and code randomly, but while it may solve the problem, those patterns will never come close to making sense to a functional programmer.

Anyway, here’s my approach:


function maxLength(initialValue, currentValue){
    var max           = initialValue,
        currentLength = currentValue.length;

        if (currentLength > max) {
            max = currentLength;
        };

    return max;
};

function hasMaxLength(element, index, array) {
    var condition = false,
        max       = array.reduce(maxLength, 0);

    if (element.length >= max) {
        condition = true;
    };

    return condition;
};

console.log(
    ["a", 0, "aa", 1, "two", 3,  "zero", "one", "four", "five", 6]
    .filter(hasMaxLength)
);

What’s left here TODO is making it work with nested array values inside the array (and perhaps some caching for the max value). This would require a “flatten” approach before “reduce” and “filter”. A “flatten” solution is actually simple to implement, if there’s demand I guess I could build a more comprehensive longest strings module. These are just some rushed up solutions.

ERATA: In the post above I’ve written that anything undeclared is undefined. I meant anything not initialized is undefined.

Thanks for the response myty. Very interesting!
I’m a bit busy tomorrow, but I’ll read what you wrote in more depth and reply back here soon.

Hi myty,

So, now I have had a bit of time to look at what you posted and work through your code.

I’ve taken on board everything you wrote in post#6, although I don’t think the author is seriously suggesting we go around writing things like Array.apply(0, Array(3));, rather just playing around with what’s possible.

As regards your code in post#7, I agree it is better to account for multiple longest strings.
However, in your solution you are invoking the maxLength callback 121 times (11 * 11).
Wouldn’t some kind of caching be appropriate here? How might one implement that?
AFAIK there is no array.flatten method in JS.

Also, you mention a functional programming approach several times in this post and various other posts.
Could you recommend anywhere where I could find a good definition of functional programming and what the main advantages/disadvantages of this approach are?
Admittedly this is something that I could Google, but if you have a recommendation I would prefer that.

This is a good place to start: http://learnyouahaskell.com/introduction#so-whats-haskell. Read at least 'till http://learnyouahaskell.com/higher-order-functions.

I’ll get back to you with the rest.

Function.prototype.memoize = function() {
   var self, cache;
   self = this;
   cache = {};
   return function () {
      var args, entry, i, cArg;  
      args = Array.prototype.slice.call(arguments);  
      entry = '';  
      cArg = null; 
      i = args.length;
      while(i--) {
         cArg = args[i];  
         entry += (cArg === Object(cArg)) ? JSON.stringify(cArg) : cArg;  
       } 
      return (entry in cache) ? cache[entry] : cache[entry] = self.apply(self, args);  
   };  
}

Then add:

hasMaxLength = hasMaxLength.memoize();

after defining the hasMaxLength function.

Then any subsequent calls to hasMaxLength with the same parameters as in a prior call will just return the same results as that prior call directly from the cache.

@James_Hibbard;

Hi there.

One way of doing it is to pass it to the filter function callback. There is the possibility to pass an object to the callback, which can then be referred to as this. We simply build this object using the object literal syntax and pass it. It has only one entry: max. Then we simply call this.max inside the callback.


function maxLength(initialValue, currentValue){
    var max           = initialValue,
        currentLength = currentValue.length;

        if (currentLength > max) {
            max = currentLength;
        };
        
    return max;
};

function hasMaxLength(element, index) {
    var condition = false;

    if (element.length >= this.max) {
        condition = true;
    };

    return condition;
};

myArr = ["a", 0, "aa", 1, "two", 3,  "zero", "one", "four", "five", 6];
console.log(myArr.filter(hasMaxLength, { max: myArr.reduce(maxLength, 0) }));

We need to build it, but it’s not that hard. I’ll put something together later.

I found this, a more recent article from an author I personally appreciate: http://tech.pro/tutorial/1611/functional-javascript
You can also check out his free ebook: JavaScript Succinctly.

Thank you. I’m off on vacation for a couple of weeks, so this’ll make for some good reading material.
I’m also reading the first chapter of Functional Programming in Scala, which seems quite promising.

Hi felgall,

I was having a bit of a discussion with myty lately regarding memoization, so was quite annoyed with myself that I didn’t at least hit upon this method as a possible method of caching the results.

Thank you!

That’s neat and simple! Thanks.
Had I had to do this for real, I think I would have got there in the end, but my solution would have been (much) more complex than necessary.
I’m hoping that by learning a little more about programming styles, I will be better equipped to choose the right tools for the job.

Me and you both. Enjoy your vacation. :slight_smile: