Blocs, Procs and Lambdas

DBC Week 6: Challenge #6

June 6, 2015

    If you are as new to programming as I am, you may have experienced what I like torefer to as the sweat reaction that comes from encountering terms and concepts that seem foreign or a bit high-brow. C'mon admit it, you've been there. When seeing a phrase like 'create an algorithm' my heart rate and blood pressure increase, my palms get a little slick and I think to myself 'how the hell do I do that? I studied German not Math!' However, after taking a minute to think, it becomes clear that algorithm is just a fifty-cent word for a list of procedures. I have been creating and using them with relative ease for the past few weeks. Once settled down I can get to work and try to actually learn something.

    Try this one on for size. Blocks! Procs! Lambdas! Blocks and Procs and Lambdas, oh my! Is your heart beating a little faster? Are you warmer than you were before reading that last line? Have you run for a paper towel to blot your palms? Well I hope not, I wasn't trying to frighten you.

    I'm like to take a minute of your time to break these three terms down into their basic parts: what they are and how they work. Hopefully by the time you finish reading this these terms will become more like a friendly face you are happy to recognize rather than a dude lurking in the shadows with his hood up on a hot night, just staring at you.

    Here it goes, short and sweet with examples to follow.

    A block is simply a piece of code that can be executed. The block is the code contained between the '{ }', or bound by the 'do' and 'end'. You might recognize it from such syntax as:

or:

    Simple enough right? All that's going on is that the method 'each' grabs each vegetable in the array of vegetables, the block takes control of the action and acts on a vegtable, and finally block gives the control back to 'each' until every vegetable has been dealt with. The issue is that the block is not an object, it can't saved to a variable and be reused. If you wanted to use this same block again it has to be typed out in the code each time you need it.

    Thinking about the block in the above example, you realize that you like to eat many other foods than just what is in the vegetable array. If the block from above (I love to eat #{item}!) could be saved as a variable, you then could call it as an argument to a method and use it on other arrays, say fruit, meats or nuts.Now, young Rubyist, meet the proc. In the simplest of terms a proc is a saved block. Proc is its own class, so when you create a new proc, you are creating an object. Check it out:
    To define a proc set a variable equal to Proc.new followed by the block to be saved:

    Now 'food_message' is a saved block, and it can be passed in to any method that takes an argument and be used over and over on other arrays. The only thing you have to remember is that methods deal with blocks, not procs. You need to trick the method into thinking it is dealing with a block, and not your new proc. You do this simply by preceeding your proc with the '&' sign. The unsuspecting method never knows the difference!
    Interestingly enough you can call a proc directly by using the '.call' method. What? Use a method on a proc? Remember, it's an object. In the case of this example we can go ahead and use the method on the proc and pass it a new item. Look:

    And now what about lambdas then you say? Well, strangely enough a lamdba similar to a proc in many ways. In fact, ouside of syntax and a couple behaviors, they are really identical. You can even think of a lambda as the shorthand version of a proc (even though it's not all that much shorter when you put them side by side). Let's look at this one step at a time:
    Lambdas, like procs, are objects. They are defined with the keyword lambda followed by a block, like this:

You can also set the lambda to a variable like you can with a proc: To pass the lambda to a method as an argument, you have to fool the method by preceeding it with the '&' sign, just like a Proc:     Just like a proc, you can call a lambda directly with the '.call'method:
    Now comes the fork in the road. There are two places where procs and lambdas diverge in how they work. The first fork has to deal with the arguments passed to procs and lambdas. A lambda checks the number of arguments passed to it. If the number of arguments passed in doesn't match up, the lambda throws an error. Take a look:
    The lambda 'grouchy_message' that we set up earlier is expecting an 'item' for it to run. If it doesn't see an 'item' as an argument, we get the above error. Here's how it looks to make it work:
    On the other hand, the proc could care less about the number of arguments. The proc is going to run either way, becuase it doesn't check. Look:

    The other fork in the road of how these two work has to deal with how they treat a return. Remember that when you use 'return' in a method definition, once Ruby reads that return, its going to output whatever it is told to return and then leave the method, as opposed to a 'puts' that will output something and then continue with the method definition. If you tell a proc to return something, it is going to evaluate it immediately and leave the method definition. While using 'return' the proc is going to assume all control and exit the method definition. The lambda on the other hand, is going to lay down and let the rest of the method definition run. It will let Ruby go ahead and do the its normal thing of evaluating the last line that it reads. Check out an example to make sense of it:

    I hope that this explanation of blocks, procs and lambdas had shed some light on what they are and how they work. Keep in mind that this is just simple introduction into these topics. This was meant to get you familiar with the basis of these Ruby concepts so that you can go forth and expand your understanding. If you find something really cool, send me an email with a link I'd love to check it out. And as always, if you have questions or notice something where I have missed some crucial understanding in this post, please don't hesitate to contact me.