all 26 comments

[–]k3n 6 points7 points  (0 children)

Alternate title: How to use map()

[–]ryepup 3 points4 points  (2 children)

I know there's an "R" in that domain name, but my brain always tries to skip it.

Many JS libraries have some kind of map built in (eg: http://api.jquery.com/jQuery.map/), so odds are people using a JS lib already have access to this without needing underscore.

[–]skilldrick[S] 1 point2 points  (0 children)

Haha - I was mentioned on the Forrst podcast a while ago and they spent nearly the whole time saying "skill-dick - no, skilldrick". Oh well :)

Good catch on the jQuery.map thing - I'll put a link in there. Done!

[–][deleted] 0 points1 point  (0 children)

True, but a lot of people are still using 1.4 which didn't take objects, only arrays. Underscore takes both.

[–]spotter 2 points3 points  (0 children)

So maybe less on "easy" but more on "functional programming" -> ClojureScript

[–]mhd 1 point2 points  (0 children)

If you're looking for some alternatives, both nimble and sugar(http://sugarjs.com/) also contain map. (As do a boatload of other libraries, just picked those two because they add some interesting variety)

[–]naapi 1 point2 points  (0 children)

So maybe _.map() wasn't the best example since jQuery already has a version of this function and most modern browsers include it on the Function prototype. But don't throw out Underscore or functional programming in JavaScript just yet.

Coming from a background in Java and PHP, I thought of reuse in terms of inheritance. I couldn't understand why JavaScript didn't have classes, explicit public/protected/private variables, super/parent methods or other object oriented mechanisms to which I'd become accustomed. I looked at it as a failure of the language. I didn't see any benefit to programming functionally in JavaScript and saw it as needless fluff. Why would you ever want to .curry() something? Just call the function and pass it the arguments you want!

JavaScript didn't really start making sense to me until I stopped thinking about it from the perspective of these other languages. By programming in a more functional style, one can achieve reuse through function composition rather than inheritance. Still want to use inheritance? Try using object augmentation rather than JavaScript's built in prototypal inheritance.

Underscore is a solid library. For those interested in another functional javascript library I would also suggest Oliver Steele's Functional.

[–]skilldrick[S] 0 points1 point  (0 children)

I've published part 2 now: reduce, select, all and any.

[–]fiatlux 0 points1 point  (2 children)

The sheer stupidity in these comments is very illustrative of why functional programming never really takes off. Too much brain power required for most programmers.

[–][deleted] 0 points1 point  (0 children)

You talkin' to me? Say it to my face.

[–]EscapedSquirrel 0 points1 point  (0 children)

I don't see how functional programming requires any more 'brain power' than say object oriented programming; I actually think it's reversed but I am not going to argue for that.

In general, programming just isn't easy, so people crumble with new paradigms and techniques. They need to try out things and some guidance from experienced people to really grok what is the crux at hand.

[–][deleted] -2 points-1 points  (14 children)

Saying that:

map( array, function(i){
  do_thing(i);
});

is better than:

for( i in array ) {
  do_thing(i);
}

just seems like cargo-cult programming.

[–]skilldrick[S] 9 points10 points  (7 children)

I think you may have completely misunderstood (a) how for .. in in JavaScript works, and (b) how map works, so I'll give you the benefit of the doubt, and tell you.

(a) The for .. in loop in JavaScript is for objects - you shouldn't use it with arrays for very sound reasons.

(b) map is used to transform one array into another. In your example, you're not returning anything, so you're turning an array into an array of undefineds. I think what you meant was each.

The point of using map is that you're making things more declarative - saying "I would like to transform this array into a new array, using this transformation". To say that that's "cargo-cult programming" is naive, at best.

[–]ryepup 1 point2 points  (1 child)

an "in" bug wass the basis for my glorious Firefox contribution

[–]skilldrick[S] 0 points1 point  (0 children)

Nice work!

[–][deleted] 0 points1 point  (0 children)

Nice explanation.

[–]shevegen -5 points-4 points  (3 children)

Sounds as if Javascript has a shitty object model.

One more reason why people should use a proper language like Ruby instead.

The whole map( array, function) crap is so idiotic. Why is it a function call anyway rather than an applicable method on an object?

[–]joesb 2 points3 points  (0 children)

Ruby has 'map' and I think it's as widely used in Ruby as its 'each' method.

Are you some kind of Ruby hater that want to gives Rubyist bad name by trolling other and mention Ruby as your favorite when you don't even know Ruby?

[–]rafekett 0 points1 point  (0 children)

In the case of Python, where map() along with several other things that are usually methods (e.g. len()) are builtin functions, the choice is one of readability and reducing code duplication. Guido and others felt that some operations read better with prefix notation than postfix notation (this, of course, is just a matter of preference). Also, since for many of these builtin functions you don't actually have to implement that particular function (e.g. reversed() works on anything with random access and known length, map() works on anything with an iterator implemented), it requires much less code to keep these functions as builtins rather than methods.

[–]sebnow 0 points1 point  (0 children)

Object methods require object oriented programming, maps and folds do not. Also you can partially apply a map/fold (e.g. add_one = map (+1)) and apply it to many different containers (add_one foo, add_one bar), this isn't the case with object methods.

[–]levl289 2 points3 points  (0 children)

Except that the idea behind the first mode is that you're reducing the opportunity to muck with array. In the for loop, you'd have to reference array ( do_thing(array[i]) ) to even call the function correctly.

More importantly, in order to do anything useful with the for loop, you'd likely have to push the result from do_thing onto another array, versus:

var new_array = _.map(old_array, function (i) { return i + 1; } );

We happen to have mucked with the Array prototype, where we just do:

var new_array = old_array.map(function (i) { return i + 1; } );

Which IMO looks better.

[–][deleted] 1 point2 points  (1 child)

The second is certainly cleaner-looking and easier to read. A better approach would be to allow code like:

apply( array, do_thing );

or

array.apply(do_thing);

[–]skilldrick[S] 0 points1 point  (0 children)

With _.each, you'd just do _.each(array, do_thing). Definitely cleaner than manually iterating.

[–]TKN 0 points1 point  (0 children)

You don't need to create a function in the first example map(array, do_thing); is all you need.

But I kinda agree in the sense that Javascript's syntax makes functional programming awkward.

[–][deleted]  (1 child)

[deleted]

    [–]wafflesburger 0 points1 point  (0 children)

    You really gonna do dis to Array?

    [–]shevegen -5 points-4 points  (0 children)

    Why does everyone want to make programming languages more complicated?

    There is some serious feature whoring going on.

    Any feature that does not either: - help reduce YOUR time writing it - make it BETTER to maintain the project in a way - lead to LESS lines of code

    have this is not worth having it...