Nested module definitions

When we define nested modules like this:

module A
  X = 1
  module B
    X = 2
    module C
      def self.print_const
        puts X
      end
    end
  end
end
  A::B::C.print_const  => 2

and when we do like this:

module A
  X = 1
  module B
    X = 2
  end
end

module A
  module B::C
    def self.print_const
      puts X
    end
  end
end
  A::B::C.print_const  => 1

Even though both method calls to print_const looks same, and should return same result. But it returns different values of the constant.

Reason:
When you do this in first case:

module A
  X = 1
  module B
    X = 2
    module C
      puts Module.nesting
    end
  end
end

and this gives:

[A::B::C, A::B, A]

So ruby looks for the constant X in the order as A::B::C, A::B, A. and it loads wherever it finds first, and as in our scenario, under module B.

And in second scenario:

module A
  X = 1
  module B
    X = 2
  end
end

module A
  module B::C
    puts Module.nesting
  end
end

and this gives:

[A::B::C, A]

Here since the nesting of the module is different, it only search in A::B::C and A, skipping A::B. So it finds constant X under module A.

Advertisements

Blocks, Procs & Lambdas revisited

Blocks, Procs & Lambdas are one of the most fun things in ruby but also very difficult to understand. This is my attempt to make these things a little simple for you.

What are blocks?

A piece of ruby code within a do..end or within curly braces {} is a block. For ex:

[1,2,3,'a'].select do |d|
  d.is_a?Integer
end

or

[1,2,3,'a'].select {|d| d.is_a?Integer}

We should also notice here that blocks breaks one of the most basic and yet powerful fundamentals of ruby that everything in ruby is an object. Well blocks are not objects. They are just piece of ruby code.

Now imagine when we have more than 1 array to select only the integer values. Ex:

[1, 2, 3, 'a'].select {|d| d.is_a?Integer}
['b', 'c', 5].select {|d| d.is_a?Integer}
['a', nil, 4 ].select {|d| d.is_a?Integer}

This is not very ruby like. We clearly breaks the DRY(Do not repeat yourself) rule. We are repeatedly writing the same block of code again and again. Now only if we could somehow save the block of code in a variable. Enter Proc.

What is a Proc?
In most simple way, Procs are named blocks. For ex:

p = Proc.new {|d| d.is_a?Integer}
puts p.class => Proc

So p is an object of class Proc unlike blocks.
Now we know how to save a block of code in a variable, lets use that knowledge to make our code dry.

[1, 2, 3, 'a'].select(&p)
['b', 'c', 5].select(&p)
['a', nil, 4 ].select(&p)

Then, what about lambda.

What is a lambda?
Lambda is just like a proc with very subtle differences between them. But before we get there, lets see how do we declare a lambda and how to use it. Ex:

p = lambda {|d| d.is_a?Integer}
puts p.class => Proc
[1, 2, 3, 'a'].select(&p)
['b', 'c', 5].select(&p)
['a', nil, 4 ].select(&p)

Yes, lambda and proc both belong to class Proc.

Then, is there any difference between them?

Difference between proc and lambda:

1. Proc do not care about the number of arguments passed. It assigns nil to any missing argument.
Ex:

p = Proc.new {|d| p d.class}
p.call => NilClass
p.call(3) => Fixnum

But had it been a lambda,

p = lambda {|d| p d.class}
p.call would raise
ArgumentError: wrong number of arguments (0 for 1)

, as it cares about its arguments unlike Procs.

2. when lambda is called, it returns control back to the calling method. Whereas Proc does not go back to the calling method. Ex:

def test_proc
  p = Proc.new {return 'In proc'}
  p.call
  'In test_proc method'
end
test_proc=> 'In proc'
def test_lambda
  p = lambda {return 'In lambda'}
  p.call
  'In test_lambda method'
end
test_lambda=> 'In test_lambda method'

I hope this would make understanding these concepts a little bit easier.