Mittwoch, 20. Februar 2013

The quick Proc

In the previous post Yield your block in Ruby I described how to code a block and its short cut "yield". You may have noticed that another kind of closure, the Proc. The goal behind is the same as the already explained block. But you will get into the situation to save a block for later dynamic use. I used a Proc the first time in my very first Ruby On Rails project.
That's why I also explain the Proc in a Rails example now.
Let's assume a model Machine:
class Machine
  attr_accessor :in_progress
  attr_accessible :name
  validates :name, :presence => true, :unless => Proc.new { |machine| machine.in_progress.blank? } 
end
having the accessor methods generated through "attr_accessor". Furthermore there is the model attribute "name" for the machine name. I want the machine validate its name for presence only in the case of the machine was already started.
That's why there is the third call "validates". And it is only called, when the :unless key contains a false. Since the validation call is dynamic, there is a Proc assigned. It executes its code not before the validation call and can return true or false depending on the value of the instance variable @in_progress.
I agree, the logic of the Proc also could be put into an instance method, say "in_progress?" (as it would be generated by Rails, if it was a model attribute).
But why should I? I only need the logic once and this way it is more readable, because it is located next to the key.
So when do I use a Proc?
I do, when some logic should be called dynamically and not be put into a method for some reasons.

Supported by Ruby 1.9.3, RubyOnRails 3.1

Montag, 11. Februar 2013

Yield your block in Ruby

In Ruby there are some topics which are not often discussed and even some developer not really know about. One of them are closures.
The Ruby closures are called blocks, Procs and lambdas. They enclose logic, which can be invoked outside of its immediate scope.
Every Ruby developer already used a block when running the well known Array#collect! or Hash#select!. An easy to understand (and 100% true) example:
languages = ["Ruby", "Python", "Javascript"]
languages.collect! do |language|
  "#{language} is awesome!"
end
The introduction so far. But how does the Proc behind (e.g. Array#collect!) work, how to do something similar and when to use it?
To illustrate the functionality of such closure I start with the Proc itself:
class Array
  def power!(&block)
    self.each_with_index do |number, index|
      self[index] = number * number
      block.call(self[index])
    end
  end
end
I re-opened the Array class and added the power! method. I sticked to Ruby conventions and put a bang at the end (if you don't know why, read about the bang convention). The method itself expects a block (or rather enclosed logic) to be passed. That is why there is an ampersand before the block parameter. Inside it only iterates over its items, squares each and calls the block on the result. Quick & simple.
The Proc is called:
numbers = [1, 2, 3, 4]
numbers.power! do |number|
  puts number
end
and prints:
1
4
9
16
 => [1, 4, 9, 16]
Well. Simple but pretty static. The call of "puts" is injected into the scope of the method "power!" by putting it into the block. Let's enhance the same example and rename the method:
class Array
  def iterate!(&block)
    self.each_with_index do |number, index|
      self[index] = block.call(number)
    end
  end
end
The method "iterate!" is pretty comparable to the stuff Array#collect! does. It iterates over each item and stores the result of the called block. In a conclusion "iterate!" offers much more dynamics. We also could square:
numbers = [1, 2, 3, 4]
numbers.iterate! do |number|
  number * number
end
There is a keyword known for calling the block. Its name is "yield". Using it you don't pass a "&block" to the method. The Array#iterate! would look like:
class Array
  def iterate!
    self.each_with_index do |number, index|
      self[index] = yield(number)
    end
  end
end
Finally I want to point out that you also can pass as much as parameters as you need to your closure. An example with two parameters would be:
class Array
  def iterate_with_index!(&block)
    self.each_with_index do |number, index|
      self[index] = block.call(number, index)
    end
  end
end
and calling it:
numbers = [1, 2, 3, 4]
numbers.iterate_with_index! do |number, index|
  puts index
end
returns:
0
1
2
3
 => [nil, nil, nil, nil]
I use blocks to keep my code DRY and to achieve more readability. And there will be a point you can't ignore them.

Supported by Ruby 1.9.3