Jan Humphries

Object Oriented, Results Oriented

Feb 1, 2015

It all begins with a block

Methods contain two elements: parameters (or variables) representing objects, and blocks, the action for those objects. This is the core of object-oriented programming: you have objects, and you have the action between them. Like nouns and verbs, as they say.

Blocks are the functional portions of methods, the portion contained between def my_method and end.


    def my_method(param)  # I am not a block
      puts param          # I am the block!
    end                   # I am not a block
    

Blocks are not objects! Ruby's world of Everything Is An Object, blocks are not objects. However, you can wrap them in a Class called Proc, which results in a function object, or closure.


    Proc.new {|param| block}  # I am an object containing a block
    # Which is like writing
    def proc(param)           # I am an object containing a block
      block
    end
    

Lambdas are things


    def proc(param)           # I'm named "proc"
      block
    end
    lambda { |param| block}   # Equivalent function, but no name
    

Lambdas are a special type of Proc. They are functions without names, and also return results in a different way. (See? Tied in the title there.) Lambdas return the last line of the method as the return value, just like we are used to seeing in methods. This is different from basic Proc behavior, which is to exit the containing method when read in a block, regardless of location in the method. Let's look at some lambda code:


      puts Proc.new {} # => <Proc:0x007fbd8a0205e0@(irb):1>
      puts lambda {}   # => <Proc:0x007fbd8a023718@(irb):2 (lambda)>

      def return_results
       Proc.new { return "I'm in the Block" }.call    # Proc called here exits
       return "I'm in the Method"                     # us from the method
      end                                             # immediately
      # return_results => "I'm in the Block"

      def return_results
       lambda { return "I'm in the Block" }.call    # Returns results back to lambda
       return "I'm in the Method"                   # Exits us from the method
      end
      # return_results => "I'm in the Method"
    

One final note:


    # BTW, writing this:
    lambda { |param| block }
    # is the same as writing this:
    lambda do |param|
      block
    end
    

And the very helpful resource rubymonk.com tells us

[T]he convention followed in Ruby is to use {} for single line lambdas and do..end for lambdas that are longer than a single line. Source