Closures in Ruby
Develop an understanding of what closures are, how and when to use them in ruby.Asad Ahmed
November 09, 2022Ruby is an amazing programming language rich in features that encapsulate and make working with the language easier compared to other Object Oriented languages. At Harled Inc, we use Ruby and Ruby on Rails everyday to deliver high impact projects to our clients. We use closures to simplify, encapsulate and pass around data in our projects.
In this post, I will explain what closures are, the types of closures in Ruby and how to use them.
What is a Closure?
A closure is a section of functional code that has variables connected to the context in which it is invoked. A closure has a few characteristics, one of which is that it can be passed as an object, although it is not necessarily an object. Another important trait of a closure is that it 'remembers' the variables within its scope at the time of creation. When that closure is invoked, it preserves knowledge of its lexical context at the time it was defined since it can access variables that might not be in the current scope.
Block
Blocks are code snippets that can be created and executed later. In Ruby, blocks are a simple type of closure. As mentioned above, blocks, unlike almost everything else in Ruby, are not objects. A block can accept arguments and can return a value. A block in Ruby does not have a name of its own and is always called with a function or can be passed to a method call.
How to Define a Ruby Block
Blocks are enclosed in a do ... end statement or between brackets {}.
The output of the method will be 'Hi From the method'. This is because everything inside of the curly braces is a block that was never referenced within the method. Now, let's tell the method to use the block.
Can you guess what the output would be when the method is called?
Here we used the 'yield' keyword to explicitly call the block that we passed to the method call.
The method is executed from top to bottom but when execution flow hits the yield keyword, the flow is 'paused' so that the block can be executed. After the block is done, then the regular flow of execution continues.
How Do We Pass Parameters to a Block?
Here, when the method is invoked, yield will call the block passed to the method call. The first time we pass the number 1 to the block as a parameter and it prints out the number 1. The second time we call the block, pass number 2 as a parameter and it prints out number 2.
Yield with a Return Value
We can return a value from a function that is using the yield keyword or even return the value of the block from within the method.
Proc
A "proc" is an instance of the Proc class that contains a code block to be executed in a variable. You call Proc.new and pass it a block to create a proc.
Lambda
With a few exceptions, lambdas are effectively procs. They are more like "ordinary" methods in two ways: they use "normal" returns and enforce the number of arguments given when they are called.
Instead of the arrow (->), you can also use the keyword 'lambda' to define a lambda function in Ruby.
Main Difference Between Procs and Lambdas
Procs and lambdas are virtually interchangeable, but they differ in a few ways:
- While lambdas will raise an exception if there are too few parameters, procs don't care about the number of parameters.
- Lambdas return from the lambda itself, whereas procs return from the current method.
Conclusion
Closures can be powerful when used correctly. You can write clean and readable code using these Ruby components. You can use closures to simulate Ruby classes. In addition to that, Ruby closures can be used to implement callbacks. Out of these, Blocks are the ones that you will probably interact with more on a daily basis.
I hope you have found this useful and that you have learned a thing or two about closures in Ruby. If you have any questions or feedback about this article feel free to contact me at asad@harled.ca or through LinkedIn.
Want to come and explore closures and other great ruby features with us? If so, we're actively hiring and would love for you to review out open positions!
We hope you've found this post helpful! If you have any feedback please reach out on X and we would be happy to chat. 🙏
About the author
Asad is a Full Stack Developer based out of Kitchener, ON.