Facebook Open Academy Blog

by Jussi Mertanen


Project maintained by Sonopa Hosted on GitHub Pages — Theme by mattgraham

Closures

Our feature is now done. On Monday we finished things up and on Tuesday we made the pull request. We immediately started getting feedback, and for the rest of the week we discussed our pull request with the member of the Rails community and made the fixes that they suggested. Most of the things suggested were just refactoring to make the code a bit better, but there were some real issues that got fixed as well. I think the pull request is now ready to be merged, but since an issue with locals (a parameter for a template) is yet to be resolved, it will probably not be merged before some kind of an solution for that is ready. Matthew and Aaron are working on it though, and they said we could start looking at it as well. Hopefully we can get it solved next week and get our feature merged. The problem is quite complex, so it might take longer than that. My personal pull request has still not been merged either, so next week I think I will ask the mentors if there’s anything I can do about that.

In this blog post I will dig deeper into one part of the Ruby language, closures (blocks).

Closures

Blocks, also know as closures, are a feature that Ruby got from functional programming languages. As I mentioned in last weeks post, blocks are essentially pieces of code that you can give to methods as parameters. They can help reduce repetition in the code and possibly make errors less likely. In addition, blocks are quite fun to use.

There are three types of closures in Ruby: blocks, procs and lambdas.

Blocks

Blocks are the simplest and the most used form of closures in Ruby. A block can be created with do … end like this:

some.method do
  doing
  something
end

or with curly braces like this:

some.method { doing.something unless lazy }

When choosing which syntax to use, it is important to remember that curly braces take precedence over do … else. Blocks can also be given arguments.

some.method do |x, y|
  x = y
end

some.method { |x, y| x = y }

Inside the method to which you pass the block, the place where the block is executed can be defined like this:

def method
  yield x, y
end

At the place of yield, the block that was passed to the method will be executed, and x and y will be passed to the block. When something is returned from inside the block, it is also returned from the calling method itself.

Procs

Procs are basically named blocks. Procs are useful when you want to have many different blocks and use them multiple times. A Proc is defined like this:

multiply = Proc.new do |n|
  n * 10
end

Now, when you have a methods that take a block/proc as a parameter you can pass the Proc to them.

def method(proc, n)
  proc.call(n)
end

method(multiply, 5)

Procs also make it easier to pass many blocks to a method.

Lambdas

The third and last form of closure in Ruby is lambda. Procs and blocks behave like they are a part of the method that is calling them. So if you return something from a block or Proc, it will return it from the calling method as well. Lambdas are otherwise the same as block and Procs, except when lambda returns, it hands control back to the calling method and continues its execution.

def method
  lambda { return "something" }.call
  return "this is returned from the method"
end