Filtering lists in Python, Ruby, and JavaScript

Recently I listened to Gary Bernhardt comparing Python and Ruby. In the talk Gary states that he finds Ruby code ugly and Python code beautiful. He then goes on to say that the things which reduce Ruby's aesthetic appeal are the very things which allow Ruby to do beautiful things impossible in Python.

Gary provides several examples of equivalent code in Python and Ruby to highlight situations in which one language reads better than the other, such as the following.

'\n'.join(obj.name
    for obj in (
        repository.retrieve(id)
        for id in ids)
    if obj)

ids.map do |id|
  repository.retrieve(id)
end.compact.map do |obj|
  obj.name
end.join('\n')

The Ruby code (the one beginning with ids.map) reads top to bottom and is easy to follow. The Python code is equally succinct but takes a bit of effort to decipher.

I've been greatly enjoying the act of writing JavaScript lately, so simply for pleasure I worked out the JavaScript equivalent.

My first attempt used the filter array method.

ids.filter(function (id) {
    var obj = repository.retrieve(id);
    return obj && obj.name;
}).join('\n');

filter, though, just removes from an array the items which fail the provided "test". So the code above is on the right track, but fails to produce a list of names.

reduce is the correct method for the job. reduce "reduces" an array to a single value, which could be a string, an object, another array — whatever!

Note the empty array ([]) on line 5 – that's our "accumulator".

ids.reduce(function (ids, id) {
    var obj = repository.retrieve(id);
    if (obj && obj.name) ids.push(obj.name);
    return ids;
}, []).join('\n');

Not bad. It's not as elegant as the Ruby code, but it's not "inside out" the way the Python code is.

Respond