Creating a map HOF in JavaScript and REBOL
January 27th, 2009
Image via WikipediaCoding in Factor has taught me few things. It also changed my preferences. I see now that most operations on lists of values can be very cleanly presented with 3 basics HOF (Higher order functions) on lists. Map, Reduce(Fold) and Filter. Foreach looks more and more like a GOTO to me.
For/foreach has a use case when you don’t calculate new values/value from a list, but do something for each element of a list (side effect).
I was coding a library in JavaScript recently. JavaScript doesn’t have these 3 functions natively but it’s very easy to write your own, so I did. I will just concentrate on map:
var map = function (f, arr) {
var r = [];
for (i=0;i< arr.length;i++) { r[i] = f(arr[i]); }
return r;
}
Map function here is a part of object jsGoo. And how do we use it:
map(function ( x ) { return x + 100; }, [ 1, 2, 3 ])
=== [ 101, 102, 103 ]
A week later I was coding something in REBOL and I wanted to have a simple map and reduce in my tool set too. I made my simple implementation and it worked. It’s very similar to the JavaScript implementation:
map: func [ series mod ] [
new: copy [ ] foreach item series [ append new mod item ] new
]
This is the usage, again very similar to the JavaScript usage:
map [ 1 2 3 ] func [a][ a * 100] === [100 200 300]
Well I am still a REBOL newbie and because REBOL is sort of functional language too I went asking on Altme world (where experienced Rebolers hang out) if it already has a native map and fold functions or something like them. Two developers started playing with making a map function and soon they posted a *little* more interesting and capable implementation of map:
map: func [ 'word data body ] [
foreach :word data reduce [:append [] to-paren body]
]
So what is the difference? Instead of a function you pass it a block of code. And you dynamically bind values to words that you then use in block. The result is that it looks totally like a native language construct, yet you created it with 1 – line function:
map x [1 2 3 4][x * x] === [1 4 9 16]
What is more the same 1-line map function can take a block of words to bind:
map [name surname] ["Ann" "Bird" "Jane" "Brown" ][ rejoin [ name " " surname ] ] === ["Ann Bird" "Jane Brown"]
This all is not a trick but a feature of languges that treat “code” a first class elements too (code is data etc..). Block of code is the same as block (list, array) of strings in rebol and there is no special notion of variable, everything are just words in REBOL that you can also work with and can get bind to values (or not).
Can you do something like this in your favorite langauge?
—
I started writing this post before I wrote “Expressing intent with REBOL”, that’s why I knew a little more about REBOL in that post than here.

![Reblog this post [with Zemanta]](http://img.zemanta.com/reblog_e.png?x-id=5afac1bd-936a-4c13-81c3-5a0d072a8ee2)
October 28th, 2009 at 11:58 pm
[...] Let’s remark that we are not obliged to use the bind function for the map function. You can also define the map function like this (I borrowed this to Janko): [...]