Channels ▼
RSS

Web Development

Programming in Ruby

Source Code Accompanies This Article. Download It Now.


Blocks and Closures

Ruby blocks can be converted into objects of class Proc. These Proc objects can be stored in variables and passed between methods just like any other object. The code in the corresponding block can be executed at any time by sending the Proc object the message call.

Ruby Proc objects remember the context in which they were created: the local variables, the current object, and so on. When called, they recreate this context for the duration of their execution, even if that context has gone out of scope. Other languages call Proc objects closures.

The following method returns a Proc object:

def times(n)
  return Proc.new {|val| n * val} 
end

The block multiplies the method's parameter, n, by another value, which is passed to the block as a parameter. The following code shows this in action:

double = times(2)
double.call(4) 	-> 8
santa = times("Ho! ")
santa.call(3) 	-> "Ho! Ho! Ho! "

The parameter n is out of scope when the double and santa objects are called, but its value is still available to the closures.

Modules, Mix-ins, and Multiple Inheritance

Modules are classes that you can't instantiate: You can't use new to create objects from them, and they can't have superclasses. At first, they might seem pointless, but in reality, modules have two major uses.

  • Modules provide namespaces. Constants and class methods may be placed in a module without worrying about their names conflicting with constants and methods in other modules. This is similar to the idea of putting static methods and variables in a Java class. In both Java and Ruby you can write Math.PI to access the value of p (although in Ruby, PI is a constant, rather than a final variable, and you're more likely to see the notation Math::PI).
  • Modules are also the basis for mix-ins, a mechanism by which you add canned behavior to your classes.

Perhaps the easiest way to think about mix-ins is to imagine that you could write code in a Java interface. Any class that implemented such an interface would receive not just a type signature; it would receive the code that implemented that signature as well. We can investigate this by looking at the Enumerable module, which adds collection-based methods to classes that implement the method each. Enumerable implements the method find (among others). find returns the first member of a collection that meets some criteria. This example shows find in action, looking for the first element in an array that is greater than four.

[1,3,5,7,9].find {|i| i > 4 } -> 5

Class Array does not implement the find method. Instead, it mixes in Enumerable, which implements find in terms of Array's each method; see Example 8. Contrast this approach with both Java and C#, where it is up to the class implementing the collection to also provide a considerable amount of supporting scaffolding.


module Enumerable
  def find
    each {|val| return val if yield(val)} 
  end
end
class Array
  include Enumerable
end

Example 8: Adding functionality with a mix-in.

Although a class may have only one parent class (the single inheritance model), it may mix in any number of modules. This effectively gives Ruby the power of multiple inheritance without some of the ambiguities that can arise. (And in cases where mixing in modules would cause a name clash, Ruby supports method renaming.)

Other Good Stuff

Other Ruby highlights include:

  • Classes and modules are never closed. You can add to and alter all classes and modules (including those built into Ruby itself).
  • Dynamic loading. Ruby modules (both source and binary) may be loaded dynamically, both explicitly and on demand.

  • Reflection. As well as supporting reflection into both classes and individual objects, Ruby lets you traverse the list of currently active objects.

  • Marshaling. Ruby objects can be serialized and deserialized, allowing them to be saved externally and transmitted across networks. A full distributed-object system, DRb, is written in about 200 lines of Ruby code.

  • Libraries. Ruby has a large (and growing) collection of libraries. All major Internet protocols are supported, as are most major databases. Extending Ruby is simple compared to adding extensions to Perl.

  • Threads. Ruby has built-in support for threads, and doesn't rely on the underlying operating system for thread support.

  • Object specialization. You can add methods to individual objects, not just classes. This is useful when defining specialized behavior for objects (for example, determining their response to GUI events).

  • Exceptions. Ruby has a fully object-oriented, extensible exception model.

  • Garbage collection. Ruby objects are automatically garbage collected using a mark-and-sweep algorithm. The choice of mark-and-sweep simplifies programming and makes writing extensions easier (no reference counting problems).

  • Active developer community. The Ruby development community is still a bazaar: small, intimate, and bustling. Changes are discussed openly and are made efficiently.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 
Dr. Dobb's TV