Replicating JavaScript’s callbacks and closures with Ruby’s yield and lambda

Kevin Kim
Kevin Kim
Jun 4, 2018 · 3 min read

Lately, I have been fiddling around with trying to replicate some JavaScript functions as Ruby methods.

A particular one that I have been tinkering with has been JavaScript’s Array.protype.map() method and implementing my own custom Array.prototype.myMap() method like so:

JavaScript: Array.prototype.myMap()

Array.prototype.myMap = function(cb) {
const mappedArr = [];
for (let elem of this) {
mappedArr.push(cb(elem));
};
return mappedArr;
};
[2,4,6].myMap((num) => { return num * 3 }); // [6, 12, 18]

Ruby: Array #my_map

The closest Ruby equivalent that I could come up with was the following:

class Array
def my_map
mapped_arr = []
self.each do |elem|
mapped_arr << yield(elem)
end
mapped_arr
end
end
[2,4,6].my_map { |num| num * 3 }#=> [6, 12, 18]

It looks pretty much identical here, JavaScript’s callback function denoted here as cb gets replaced as Ruby’s reserved yield keyword, and JavaScript’s this gets replaced with Ruby’s self.

If I wanted to pass in a defined callback function into my JavaScript’s myMap method, the implementation would be like this:

const tripler = (num) => {
return num * 3;
}
[2,4,6].myMap(tripler); // [6, 12, 18]

In Ruby though, we can’t just save a block into a variable like so:

tripler = { |x| x * 3 }#=> syntax error, unexpected '|', expecting '}' tripler = {|x| x * 3}

We can however, leverage lambda like so:

lam = lambda { |x| x * 3 }[1,2,3].my_map(&lam) 
# The '&' tells ruby to turn the lambda into a block
#=> [3, 6, 9]

Closure in JavaScript

This is the textbook definition of a JavaScript closure.

const multiplier = (factor) => {
return ((number) => { return factor * number });
}
const doubler = multiplier(2);
doubler(9); // 18

Closure in Ruby

The closest approximation to JavaScript’s closure in my finding has been Ruby’s use of lambda again as seen below, as lambda retains the outer scope variable of factor.

def multiplier(factor)
return lambda { |number| factor * number }
end
doubler = multiplier(2);
doubler.call(9) #=> 18

Note that we have to explicitly call on the returned lambda via call method to get the same effect as JavaScript’s closure.

Findings

Replicating JavaScript’s callbacks and closures with Ruby required uses of yield and lambda.

To say though that Ruby’s yield is basically JavaScript’s callback, and that lambda is basically Ruby’s version of JavaScript’s closure is not quite right.

There are definitely some parallels, but each languauage definitely has its own quirks in the way it handles closures and callbacks.

TLDR: Ruby’s lambda and yield can mimic some of JavaScript’s behavior in using anonymous functions and retaining functions as variables. Ruby’s lambda and yield do not have an exact 1:1 analogue in JavaScript. Ruby and JavaScript are different languages.

I hope you enjoyed this blog post. Feel free to follow me on Medium as I write weekly blog posts related to web development. Also feel free to follow me on Twitter @kevinyckim where I post daily tweets about programming epiphanies and my job search.

Kevin Kim

Written by

Kevin Kim

Front End Engineer https://kevinyckim.netlify.com/

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade