true.class # => TrueClass: true is a the singleton instance of TrueClass
false.class # => FalseClass
nil.class # => NilClass
In many languages, function and method invocations require parentheses, but there
are no parentheses in any of the code above. In Ruby, parentheses are usually optional
and they are commonly omitted, especially when the method being invoked takes no
arguments. The fact that the parentheses are omitted in the method invocations here
makes them look like references to named fields or named variables of the object. This
is intentional, but the fact is, Ruby is very strict about encapsulation of its objects; there
is no access to the internal state of an object from outside the object. Any such access
must be mediated by an accessor method, such as the class method shown above.
1.1.2 Blocks and Iterators
The fact that we can invoke methods on integers isn’t just an esoteric aspect of Ruby.
It is actually something that Ruby programmers do with some frequency:
3.times { print "Ruby! " } # Prints "Ruby! Ruby! Ruby! "
1.upto(9) {|x| print x } # Prints "123456789"
times and upto are methods implemented by integer objects. They are a special kind of
method known as an iterator, and they behave like loops. The code within curly braces
—known as a block—is associated with the method invocation and serves as the body
of the loop. The use of iterators and blocks is another notable feature of Ruby; although
the language does support an ordinary while loop, it is more common to perform loops
with constructs that are actually method calls.
Integers are not the only values that have iterator methods. Arrays (and similar “enu-
merable” objects) define an iterator named
each, which invokes the associated block
once for each element in the array. Each invocation of the block is passed a single
element from the array:
a = [3, 2, 1] # This is an array literal
a[3] = a[2] - 1 # Use square brackets to query and set array elements
a.each do |elt| # each is an iterator. The block has a parameter elt
print elt+1 # Prints "4321"
end # This block was delimited with do/end instead of {}
Various other useful iterators are defined on top of each:
a = [1,2,3,4] # Start with an array
b = a.map {|x| x*x } # Square elements: b is [1,4,9,16]
c = a.select {|x| x%2==0 } # Select even elements: c is [2,4]
a.inject do |sum,x| # Compute the sum of the elements => 10
sum + x
end
Hashes, like arrays, are a fundamental data structure in Ruby. As their name implies,
they are based on the hashtable data structure and serve to map arbitrary key objects
to value objects. (To put this another way, we can say that a hash associates arbitrary
1.1 A Tour of Ruby | 3