Simple clear advice in plain English

Hands on: The many facets of Ruby

An insight into what the dynamic language has to offer, including blocks and closures

Blocks in Ruby

The five-minute introduction above is sufficient for a look at ‘blocks’. A block is code between curly brackets or do … end. The key thing about blocks is that you can pass them as arguments.

A great place to start is Ruby’s ‘each’ method. Classes such as Array and Hash have an each method that lets you iterate through all the items in the collection.

To list all the articles in a Magazine, in VB enter:

‘VB code
For Each a As Article In pcw.Articles
Debug.Print(a.Title)
Next

In Ruby you can write:

#this is a block with do .. end notation
pcw.articles.each do
|an_article|
puts an_article.subject
end

The short version is more distinctive:

#this is a block
pcw.articles.each {|an_article| puts an_article.subject}

A block of code is being passed as an argument to the each method. The variable between vertical bars indicates a parameter.

Internally, the each method calls the block of code once for each item in the collection, passing the value of the item as an argument to the block.

Fun with blocks and closures

The above code lists the Articles in a Magazine, but how are the articles added? The obvious way is to add a method to the Magazine class. First, add a constructor to Article:

def initialize(subject,rating)
@subject = subject
@rating = rating
end

Add the following to Magazine. Note the use of the << operator which appends an item to the Array:

def add_article(subject,rating)
article = Article.new(subject,rating)
# add the article
self.articles< end

You could implement this with a block. In this admittedly contrived case, the code is passed to the method and executed with the yield statement:

def alt_add_article(subject,rating)
yield self, subject, rating
end

You could call the method like this:

#this is a block called with yield
pcw.alt_add_article(“Advice from our experts”,5) do |themag, thesubject, therating|
article = Article.new(thesubject,therating)
themag.articles< end

In the Ruby calling code, the block follows immediately after any arguments to be passed to the method. In the receiving code, the yield statement is followed by any arguments to be passed to the block.

There is a close relationship between blocks and Ruby Proc objects. A Proc object is a variable that holds a function. You can rework the alt_add_article method like this:

def alt_add_article(subject,rating,&addit)
addit.call(self,subject,rating)
end

The &addit parameter converts the block to a Proc object. This leads to another possibility, where we return a Proc object from a method. Add the following method to Magazine:

def add_an_article
return lambda do
|subject,rating|
self.articles< end
end

The lambda method converts a block to a Proc. So now you have this:

addit = pcw.add_an_article
addit.call(“Talk more, pay less”,5)

The block within add_an_article contains a reference to self, yet when the Proc is called it is no longer in the context of a class. This ability to maintain context is why Ruby blocks are also called closures.

What’s it all for?

There are several ways to look at blocks and closures. One is to note that they make functions first-class citizens.

You can treat a Proc more or less like any other variable. You also gain total flexibility over where code is situated and when it is executed.

For example, if you write GUI applications there is sometimes a conflict between putting code in the classes that define the GUI widgets, for easy access to the UI, or in the non-visual classes where it perhaps belongs.

Blocks make it possible to get the best of both worlds.

Blocks in other languages

Once you get used to the power of blocks in Ruby, you may ask if you can use them in other languages such as VB, C#, Delphi or Java. The answer is mostly ‘yes’.

Microsoft’s .Net 2.0 has support for closures, and so does Delphi. Java’s anonymous classes come close.

The Ruby advantage is that blocks are easy to use and require little code. In many cases they make code more concise. This perhaps is why blocks are used more frequently in Ruby than in other languages.

Reader Comments

   

Add your comment

All fields must be completed. Your email address will not be displayed or used to send marketing messages.

All messages will be checked by moderators before appearing on the site.

See our Privacy Policy for more information.

Related articles

Hands on: Programming with Ruby

Use it with Rails and find out how to create your web applications

Question & Answer

Q.Why are some of the keys on my keyboard doing strange...

> Read the answer

Q.Is my phone’s Bluetooth any use?

> Read the answer

Q.Can I switch boot drives so that I can work on older...

> Read the answer

Best deals on the web

img

Samsung RV520-A07

£359.98- Buy it now

img

Acer Aspire 5750G (LX.RXP02.019)

£399.99- Buy it now

img

Apple MacBook Pro (MD313B/A)

£904.37- Buy it now

Latest issue & subscription deals

Poll

Are you concerned about viruses that target mobile phones?

Jargon Buster

Computing terms explained in plain English

Restore point

A Windows backup of system files and settings.

Great shopping deals from Computeractive