Designed by Yukihiro Matsumoto in 1993; first public release in 1995.

Features

Dynamically typed (variables may contain any kind of value)

Interpreted: Ruby source code is directly loaded into the Ruby interpreter and executed. (Internally, the interpreter translates the source program into a more-easily executed format.)

Because it is dynamically typed and interpreted, Ruby is often referred to as a "scripting" language. The designation "scripting language" brings connotations of not being a "serious" language, and/or not being suitable for the development of large programs. This view is too narrow; many large programs are now developed using languages like Ruby, Python, Perl, etc. At the same time, type checking in dynamically-typed languages is generally deferred to runtime, meaning that some type errors may not be caught until the program runs. Opinions differ as to whether or not this is a serious problem.

Everything is an Object

Ruby is a pure object-oriented language; all values are references to objects. For example, each of the following two statements prints "5"

puts 2 + 3
puts 2.+(3)

The expression "2 + 3" is familiar: literal values 2 and 3 are added by an infix + operator. In most languages, values 2 and 3 would belong to a primitive integer type distinct from the universe of classes and user-defined types. In Ruby, they are instances of the Fixnum class. The second code example above makes a direct call to the + method on the object 2, passing the argument 3.

We can directly inquire the class an object belongs to by calling the "class" method.

puts 2.class

This prints "Fixnum".

Blocks

Methods in Ruby can take a code block as an argument. You can think of a code block as being an anonymous procedure passed to the called method; the called method will then call the block procedure as part of its execution.

Ruby uses blocks in many contexts where some operation is being performed on a sequence of values. For example, we can compute a factorial this way:

c = 1
(1..6).each do |n| c *= n end
puts c

Note that the value (1..6) is an instance of the Range class. Its "each" method invokes a code block for each member of the range, passing the member as the argument to the block. The code block in this code is the part between "do" and "end"; the block has a single parameter "n" which receives the value of each member of the range in sequence.

Note that we haven't declared any variable in this program: variables are created automatically as needed. (In other words, the first applied occurrence of a variable is its binding occurrence.) An uninitialized variable has a special "nil" value (like a null pointer in Java/C++).

Ruby Literals

Kinds of literal values in Ruby:

The usual numeric literals:

Kind Examples Class
fixed-precision integer 4, 17, 42 Fixnum
arbitrary-precision integer 1111111111111111111111111111111 Bignum
floating-point 001, 3.14159, 10e7 Float

All literal text, including single characters and strings of characters, are treated as Strings:

Kind Examples Class
Single-quoted string 'a', 'hello world' String
Double-quoted string "a", "hello world\n" String

Double-quoted strings support a variety of escape sequences to represent special characters. Examples:

Escape sequence Meaning
\n Newline character
\r Carraige-return character
\f Form-feed character
\b "Bell"
\ Literal backslash character
" Literal double-quote character

Single-quoted strings only support two escape sequences:

Escape sequence Meaning
\' Literal single-quote character
\\ Literal backslash character

Symbol literals are like enumeration values. They are members of the Symbol class:

Kind Examples Class
symbol value :foobar, :dog, :cat Symbol

Regular Expressions

Regular expression literals:

/ regular expression /

A regular expression's class is Regexp.

Example:

r = /foo|bar/
puts r.class
puts r.match('foo') ? 'yes' : 'no'
puts r.match('bar') ? 'yes' : 'no'
puts r.match('foobaz') ? 'yes' : 'no'
puts r.match('blat') ? 'yes' : 'no'

This code produces the output

Regexp
yes
yes
yes
no

The syntax and meaning of Ruby regular expressions is very similar to the syntax and meaning of Perl Regular Expressions.

Ignoring case in a regular expression

The "i" modifier causes a regular expression object to match case-insensitively:

#! /usr/bin/ruby

r = /foobar/i;

if r.match('foobar')
    puts "yes"
end

if r.match('FOObaR')
    puts "yes"
end

This program outputs

yes
yes

Regexp search and replace

The gsub method of the String class replaces all occurrences of substrings matching a regular expression with a given replacement string.

Example: removing HTML tags from a string.

#! /usr/bin/ruby

matchtag = /<[^>]*>/;

STDIN.each do |line|
    # Remove newline from end of line
    line.chomp!

    # Replace all occurrences of HTML tags from the string
    line = line.gsub(matchtag, '')

    # Print out line
    puts line
end

String interpolation

A double-quoted string can have the textual representations of values stored in variables automatically substituted in the string. For example:

s = 'Alice'
puts "Hi #{s}"

produces the output

Hi Alice

Note that arbitrary expressions may be used:

n = 4
puts "n + 5 is #{n + 5}"

The result of the expression is converted to a string (by calling the to_s method) before being substituted into the result string.

Classes and methods

Ruby classes and methods work more or less the same way as in C++, Java, and other object-oriented languages.

class Animal
end

class Dog < Animal
    def noise
        puts "Bark"
    end
end

class Cat < Animal
    def noise
        puts "Meow"
    end
end

fifi = Dog::new
brutus = Cat::new

fifi.noise
brutus.noise

Ruby uses the convention that an identifier beginning with an at symbol (@) denotes a field:

class Animal
    def initialize(name)
        @name = name
    end
end

class Dog < Animal
    def noise
        puts "#{@name}: Bark"
    end
end

class Cat < Animal
    def noise
        puts "#{@name}: Meow"
    end
end

fifi = Dog::new("Fifi")
brutus = Cat::new("Brutus")

fifi.noise
brutus.noise

Note that Animal's constructor method (initialize) is inherited by both Dog and Cat.

From these examples you can see that Ruby is not too different than Java and C++ in the way it supports object-oriented programming. Except...

Dynamic Object-Oriented Features in Ruby

Classes and objects in Ruby are much more dynamic and flexible than Java or C++.

For example, we can add a method to an existing object at runtime:

def fifi.walkies
    puts "#{@name} goes for walkies"
end

The method call

fifi.walkies

produces the output

Fifi goes for walkies

However, the code

rex = Dog::new("Rex")
rex.walkies

Produces the following error:

./animals.rb:34: undefined method `walkies' for #<Dog:0x100ef49c @name="Rex"> (NoMethodError)

because plain instances of the Dog class do not support the walkies method.

We can also define a method within a class whose purpose is to handle all method invocations where a method cannot be found through normal virtual dispatch.

Example:

#! /usr/bin/ruby

class All_Method
    def method_missing(method, *args)
        method_name = method.to_s
        print method_name
        args.each do |arg|
            print " #{arg.to_s}"
        end
        print "\n"
    end
end

The code

a = All_Method::new

a.hi_there

produces the output

hi_there

The code

a.i_can_do_anything 'a', 'b', 'c'

produces the output

i_can_do_anything a b c

Using this technique, we can define classes that decide what kinds of methods they support at run time rather than compile time.

Note that this would be difficult/impossible in a language that requires static type checking.