Thursday, July 24, 2014

A tour of Ruby

Share it Please

A Tour of Ruby

This section is a guided tour through some of the most interesting features of Ruby. Everything discussed here will be documented in detail later in further posts, but this first look will give you the flavor of the language.

1. Ruby Is Object-Oriented

Ruby is a completely object-oriented language. Every value is an object, even simple numeric literals and the values true, false, and nil (it is Ruby’s version of null). Here we invoke a method named class on these values. Comments begin with # in Ruby, and the => arrows in the comments indicate the value returned by the commented code:

 1.class          # => Fixnum: the number 1 is a Fixnum
 0.0.class       # => Float: floating-point numbers have class Float
 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.  

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.

The ability to associate a block of code with a method invocation is a fundamental and very powerful feature of Ruby. Although its most obvious use is for loop-like constructs, it is also useful for methods that only invoke the block once. For example:

File.open("data.txt") do |f|  # Open named file and pass stream to block
line = f.readline                 # Use the stream to read from the file
end                                  # Stream automatically closed at block end


Double-quoted strings can include arbitrary Ruby expressions delimited by #{ and }. 

 print "#{ a } + #{ b } = #{ a + b } "  # Note variables substituted into string
 
The value of the expression within these delimiters is converted to a string (by calling its to_s method, which is supported by all objects). The resulting string is then used to replace the expression text and its delimiters in the string literal. 


3 Expressions and Operators in Ruby

Ruby’s syntax is expression-oriented. Control structures such as if that would be called statements in other languages are actually expressions in Ruby. They have values like other simpler expressions do, and we can write code like this:

minimum = if x < y then x else y end

Here are examples of some commonplace and some more unusual Ruby operators:

1 + 2                                 # => 3: addition
1 * 2                                 # => 2: multiplication
1 + 2 == 3                        # => true: == tests equality
2 ** 1024                         # 2 to the power 1024: Ruby has arbitrary size ints
"Ruby! " * 3                      # => "Ruby! Ruby! Ruby! ": string repetition
"%d %s" % [3, "rubies"]    # => "3 Rubies": Python-style, printf formatting
max = x > y ? x : y            # The conditional operator


Many of Ruby’s operators are implemented as methods, and classes can define these methods however they want.

4 Methods

Methods are defined with the def keyword. The return value of a method is the value
of the last expression evaluated in its body:

def square(x)         # Define a method named square with one parameter x
x*x                       # Return x squared
end                      # End of the method


5 Assignment

The (non-overridable) = operator in Ruby assigns a value to a variable:

x = 1

Assignment can be combined with other operators such as + and -:

x += 1                # Increment x: note Ruby does not have ++.
y -= 1                 # Decrement y: no -- operator, either.


Ruby supports parallel assignment, allowing more than one value and more than one variable in assignment expressions:

x, y = 1, 2                   # Same as x = 1; y = 2
a, b = b, a                   # Swap the value of two variables
x,y,z = [1,2,3]             # Array elements automatically assigned to variables


Methods in Ruby are allowed to return more than one value, and parallel assignment is helpful in conjunction with such methods. For example:

# Define a method to convert Cartesian (x,y) coordinates to Polar
def polar(x,y)
theta = Math.atan2(y,x)               # Compute the angle
r = Math.hypot(x,y)                     # Compute the distance
[r, theta]                                      # The last expression is the return value
end


# Here's how we use this method with parallel assignment
distance, angle = polar(2,2)


6. Regexp and Range

A Regexp (regular expression) object describes a textual pattern and has methods for determining whether a given string matches that pattern or not. And a Range represents the values (usually integers) between two endpoints. Regular expressions and ranges have a literal syntax in Ruby:

/[Rr]uby/            # Matches "Ruby" or "ruby"
/\d{5}/               # Matches 5 consecutive digits
1..3                   # All x where 1 <= x <= 3
1...3                  # All x where 1 <= x < 3


Regexp and Range objects define the normal == operator for testing equality. In addition, they also define the === operator for testing matching and membership. Ruby’s case statement (like the switch statement of C or Java) matches its expression against each of the possible cases using ===, so this operator is often called the case equality operator. It leads to conditional tests like these:

# Determine US generation name based on birth year
# Case expression tests ranges with ===

generation = case birthyear
when 1946..1963: "Baby Boomer"
when 1964..1976: "Generation X"
when 1978..2000: "Generation Y"
else nil
end


7. Classes and Modules

A class is the definition of a single type of object. Class names in Ruby always start with a capital letter, so your programs will end up with classes with names like User, Person, Place, Topic, Message, and so forth.

class Person
attr_accessor :name, :age, :gender
end


8. Ruby Surprises

Every language has features that trip up programmers who are new to the language. Here we describe two of Ruby’s surprising features.

Ruby’s strings are mutable, which may be surprising to Java programmers in particular. The []= operator allows you to alter the characters of a string or to insert, delete, and replace substrings. The << operator allows you to append to a string, and the String class defines various other methods that alter strings in place.  Ruby’s conditionals and loops (such as if and while) evaluate conditional expressions to determine which branch to evaluate or whether to continue looping.

Conditional expressions often evaluate to true or false, but this is not required. The value of nil is treated the same as false, and any other value is the same as true. This is likely to surprise C programmers who expect 0 to work like false, and JavaScript programmers who expect the empty string "" to be the same as false.




No comments:

Post a Comment

Followers