Archive for the ‘Ruby’ Category

Learning Ruby [iterator control structures]

Monday, October 3rd, 2011

Iterators are methods that have the ability to iterate through a collection, such as an array or hash table. During each iteration, these methods yield one or more values to a code block that is defined when the method is called. This code block is used in different ways depending on the type of iterator method that has been called.

Before delving deeper into iterator methods, let’s take a look at the concept of yielding. The yield method enables a method to yield to a code blocks that is defined along with a method call. This means that where ever you add the keyword yield in your method, Ruby will look for a code block to insert here when the method is called. As a consequence, methods that include a call to yield require that a code block be defined when they are called.

The code blocks functions though they were running inside the method that yielded to them. Data can be shared between the method and code block. To send data to the code block, arguments can be provided to the yield method just as with any other method. These arguments are available in the code block using the syntax | var_1, var_2 |. The examples below show this in action.

def yielding_method
    puts pre-yield
    yield(message from yielding method)
    puts post-yield
end

yielding_method {|i| puts yield code block #{i}” }

view raw gistfile1.rb This Gist brought to you by GitHub.

The yield method can also return a value from the code block. It returns the value from the last expression in the code block to which it yielded – notice that this is the same rule that applies to method returns).

In the example below the value returned by the yielded method is assigned to a variable called return_vals. The actual value returned by the code block is string. If the yielding_method was an iterator method we use an array to capture the data returned from each iteration.

def yielding_method
    puts pre-yield
    return_vals = yield(message from yielding method)
    puts post-yield #{return_val}”
end

yielding_method do |i|
    puts yield code block #{i}”
    str = message from code block back to method
end

view raw gistfile1.rb This Gist brought to you by GitHub.

Now let’s take a look at the three most commonly iterator methods. Times is a popular iterator that can be called on any integer object, and it will loop from 0 until it reaches the integer number on which it was called. This method is a nice and concise way to create a simple loop. When it is done iterating, the times method returns the original integer number.

4.times {|cur_num| code block to run}
view raw gistfile1.txt This Gist brought to you by GitHub.

The each method can be used with collection classes, such as arrays. It loops through each element in the given collection class, and let’s you define a block of code that receives the current element from the collection via a parameter. When it is done iterating, each returns the original array.

my_array = [1, 2, 3, 4]
my_array.each {|cur_element| code block to run}

view raw gistfile1.rb This Gist brought to you by GitHub.

The map iterator is similar to each, in that it is designed to work with collection classes. However, map returns an array, of the same value as the original collection, containing the return values from the code block. When you use map you have to make sure that the last expression in your code block will return the value that you want to capture in the array that is returned.

my_array = [1, 2, 3, 4]
new_array = my_array.map {|cur_element| cur_element += 2}

view raw gistfile1.rb This Gist brought to you by GitHub.

Learning Ruby [loop control structures]

Monday, October 3rd, 2011

Ruby provides several different types of looping control structures. The most basic ones, which I will cover here, are the loop, while and for statements.

The loop method is used for unconditional looping. These loops will cycle continuously until the keyword break is used to stop it. The keyword next can also be used to make the loop jump to the next iteration, skipping any code that defined after it. The code block associated to a loop can be enclosed by {} or the loop and end keywords.

x = 0
loop
    x += 1
    puts "current count #{x}"
    next unless x > 5
    break
end

view raw gistfile1.rb This Gist brought to you by GitHub.

While and Unless are conditional loop structures that will loop continuously until a certain condition is met. The while method will loop for as long as the condition is met; the unless method functions in the same way but with the inverse logic, it loops for as long as a condition is not met. These types of loops can be defined using three different syntax structure, one of these functions a bit differently from the other two so make sure to choose between them wisely.

The most common style for while and unless loops places the condition at the top of the code block, with the keyword end closing out the code block. For looping through a single expression you can use a one line statement that that starts with the expression followed by the while keyword with the condition. Either of these approaches only execute the code if the condition is met (or not, in case of unless).

The syntax option uses the begin keyword to start out the code block, which is closed by the end and and while/unless keywords followed by the condition. This syntax always executes the code block at least once, even if the condition is not met.

puts "while/end loops"
x = 0
while x < 5
puts "while current index #{x}"
x += 1
end

x -= 1 while x > 0

puts "begin/while loop"
begin
puts "while current index #{x}"
x += 1
end while x < 5

view raw gistfile1.rb This Gist brought to you by GitHub.

In ruby the for loop is designed to loop through collections such as arrays, hash tables, and series. The syntax is nice and concise, as shown below. Please note the cur_element is a assigned the current element of the array during each loop iteration.

array = ["loop", "spin", "cycle", "repeat", "iterate"]
for cur_element in array
    puts cur_element
end

for cur_element in (0..10)
    puts cur_element
end

view raw gistfile1.rb This Gist brought to you by GitHub.

Learning Ruby [methods and messages]

Monday, October 3rd, 2011

Let’s dig a little bit deeper into methods. First let’s take a look at some basic stuff, like how methods are called and defined. Methods calls contain three parts: first the object name followed by a dot; next the method name; and lastly the arguments, which are usually enclosed in parentheses.

obj.method_name(arg_1, arg2)
view raw gistfile1.rb This Gist brought to you by GitHub.

If you are calling a method from the same object you do not need to specify the object at the beginning of the method call. For example, the expression above could be changed to method_name(arg_1, arg_2). When a method call does not feature an owner Ruby assumes that the owner is the current self.

Now let’s move on to method declarations. In the code example above, you can see that a method declaration begins with the keyword def. This is followed by the method name, which has to start with a lower case letter (with some exceptions). Lastly, you have a set of parenthesis that holds a list of input parameters (or arguments).

Ruby supports three different types of input parameters. Standard input parameters must align one to one with input arguments. So if you have a method with input parameter (a, b, c) then this method must be passed three input arguments when called.

Ruby also supports expandable parameters that can hold a variable number of arguments, including none at all. These parameters are identified by an asterisk (*a). Lastly, methods can also feature parameters with default values, such as (a=1). When calling a method that features a parameter with a default value you can choose to omit that argument. Below is a sample method with multiple input parameter types.

def parameter_madness(a, b=1, *c, d)
    puts "a = #{a.to_s}"
    puts "b = #{b.to_s}"
    c.each_with_index { |c, i| puts "c number #{i.to_s} = #{c.to_s}" }
    puts "d = #{d.to_s}"
end
view raw gistfile1.rb This Gist brought to you by GitHub.

When Ruby distributes a method’s parameters it goes from right to left but it always prioritizes the standard parameters, where ever they may be. Secondly, it passes arguments to parameters with default value, and lastly supplies the remaining values to the expandable parameter.

Method Introspection and Reflection
Ruby has some really cool functionality for handling methods that are enabled by its reflective and introspective capabilities. First off, you can ask an object if it is able to respond to a message by calling the method respond_to?(:“method name”). This method returns true or false, depending on whether the given object has a method with the name specified in the argument.

You can also call a method by using the send(:“method name”) method. These two methods are designed to be used together to enable you to easily check whether an object can handle a certain message/method, and then call that method if appropriate.

Another cool feature is the ability for objects to handle calls to non-existent methods by capturing these events using the method_missing method. This ultimately makes it possible for an object to respond to methods/messages that are defined dynamically during run time. It also enables objects to pass along method/messages to other objects, if they are not the appropriate responders. I’m sure there is other cool stuff that can be done with this, which I will learn as I start to play around more with Ruby.

Accessing Inherited Methods
The Super is a keyword is used by a method within a class or module to call up a higher-up version of the same method. In Ruby there are three different ways to call “super”. You can call “super” with no arguments, super, in which case any arguments that were passed to the to the method which is calling super will automatically be passed along. You can call “super” with an empty argument list, super(), in which case no arguments are sent to the higher-up version of the method. Or, wou can call “super” with specific arguments – super(a, b) – in which case only the arguments that are specified will get passed on to the higher-up version of the method.


Learning Ruby [conditional control structure]

Monday, October 3rd, 2011

Ruby features a variety of conditional control structures that are used to guide the flow and logic of programs. I will cover these briefly here because they don’t differ much from other languages.

The most common one is the if statement, which controls the flow of a program based on the evaluation of conditional statements. If statements are often chained together with else and elsif statements that enable the program to support multiple different flow-routing possibilities. They can be defined using four slightly different syntaxes.

  1. Separates the statement across multiple lines. The end keyword is used to identify the end of all conditional statements (if/elsif/else).
  2. Single line approach that uses the keyword then to separate the condition from the single expression that serves as the code block. The statement is close the keyword end.
  3. Single line approach that uses ; to separate each line of code between the if statement and the keyword end.
  4. Uses a single line that starts with the expression that will be run if the condition, which expressed at the end of the line, is met.

Examples of all four approaches are featured below:

condition = false
condition_else = true

# traditional verbose approach
if condition
    puts "condition 1 true"
    elsif condition_else
        puts "condition_else true"
    else
        puts "it's all a lie"
    end

# single-line approaches
if condition then puts "condition 2 true" end
if condition; puts "condition 3 true"; end
puts "condition 4 true" if condition

view raw gistfile1.rb This Gist brought to you by GitHub.

Unless is a conditional statement works the same as if, but with the reverse logic. This statement runs the code block as long as the condition evaluates to false; in other run, it executes a block of code unless the condition is true. The syntax for unless supports else statements like if.

Case statements are the other conditional structure available in Ruby. These expressions are highly customizable. Unlike many other languages, Ruby allows you to specify the matching logic used by case statements. The method that contains this match logic is called ===, so by redefining this method you can change how a case statement will identify matches.

The general syntax for a case statement is outlined below. However, what makes case statements really useful is that an instance method is responsible for defining when a case matches one of the conditions. By redefining this method in your custom created classes you can make it possible for you to use a case statement to on objects of that class.

con_a = 0; con_b = 1; con_c = 2
test = 2

case test
    when con_a
        puts "test value met condition a"
    when con_b
        puts "test value met condition b"
    when con_c
        puts "test value met condition c"
    else
        puts "test value not in range"
    end
view raw gistfile1.rb This Gist brought to you by GitHub.

In Ruby you can also use case statements without a test expression. In these instances the script just tests for the truth value of each condition. The first one that resolves to true is the winner. Of course, when a case statement is used in this way the conditional expression that follows each when keyword is more akin to those that usually follow if statements.


Learning Ruby [scope vs. self and variables]

Monday, October 3rd, 2011

Before talking about the different types of variables it is important to become familiar with how Ruby handles the concepts scope and self. All local variables are restricted to the scope in which they were created, while all instance variables are restricted to the self in which they were created.

Scope is defined based on code blocks such as methods, and classes. Every time you cross one of these boundaries you enter into a new scope. The illustration below shows how the class, and each method has a scope of its own. This means that local variables defined within each of these scopes is only accessible inside the scope.

class MyClass #class scope
    x = class_scope #class scope
    def my_method_1 #class scope
        x = 0 #my_method_1 scope
        (0..5).each do |n| #my_method_1 scope
            x += x #my_method_1 scope
        end #class scope
    end #class scope
    def my_method_2 #class scope
        x = 0 #my_method_2 scope
        (0..5).each do |n| #my_method_2 scope
            x = n #my_method_2 scope
        end #class scope
    end #class scope
end #class scope
view raw gistfile1.rb This Gist brought to you by GitHub.

At any given moment in a Ruby program there is an object that is calling the shots. This “active” object is always considered to be the program’s self. This self is constantly changing, as the program jumps from one method call to another. The scope of instance variables is always defined based on the self to which they are related. An object only has access to the instance variables that are defined as part of it’s self. The illustration below shows how different parts of a class definition are related to different concepts of self.

class MyClass # class instance
    def self.class_method # class instance
    end # class instance
    def self.class_method_2 # class instance
    end # class instance
    def instance_method # object instance
    end # object instance
    def instance_method_2 # object instance
    end # object instance
end # class instance
view raw gistfile1.rb This Gist brought to you by GitHub.

It is important to remember that classes are themselves object instances of another class named Class. This means that there are instance variables associated to a class object, and then there are the instance variables that are associated to the objects that are created (or instantiated) from a class. To make matters more complicated, class variables also exist. Class variables differ from the instance variables of a class because they are shared between the entire class hierarchy including the objects that have been created from that class.

class MyClass
    @@class_variable #class-hierarchy variable
    @class_instance_variable #class instance variable
    attr_accessor :object_instance_variable #object instance attribute
#__variable with getter & setter

    def self.class_method
local_method_variable #local method variable
        @class_instance_variable #class instance variable
        @@class_variable #class-hierarchy variable
    end

    def instance_method_1
local_method_variable #local method variable
        @object_instance_variable #object instance variable
        @@class_variable #class-hierarchy variable
    end

    def instance_method_2
local_method_variable #local method variable
        @object_instance_variable #object instance variable
        @@class_variable #class-hierarchy variable
    end
end

view raw gistfile1.rb This Gist brought to you by GitHub.

Ruby’s strict enforcement of variable self and scope rules means that methods are the only way for different objects to communicate with one another. When talking about methods things are a bit simpler. There are three types of methods associated to objects: instance methods describe the behaviors provided by objects that are created (or instantiated) from a class; class methods describe behaviors provided by the class object itself; singleton methods describe special behaviors associated with a individual objects that have been instantiated from a class.

Unlike variables, methods from an object can be accessed by other objects. That is why in Ruby you always need to define getter and setter methods for instance variables that need to be accessed from outside of their own “self”. Attributes is a shorthand feature provided by Ruby that creates instance variables along with getter and setter functions.

There are three types of attributes: reader attributes consist of an instance variable along with a getter method; writer attributes include an instance variable and a setter method; accessor attributes consist of instance variables along with both getter and setter methods. The name of each attribute must be defined using a symbol, as outlined below.

attr_reader : var_with_getter
attr_writer : var_with_setter
attr_accessor : var_with_setter_and_getter
view raw gistfile1.rb This Gist brought to you by GitHub.

Here is an overview of the different types of variables and constants available in Ruby, along with a note regarding the scope or self to which they are limited.

#VARIABLE DESCRIPTION NAMESPACE
#var local variable scope-based
#$var global variable accessible anywhere
#@var instance variable self-based
#@@var class variable class hierarchy-based
#Const constant accessible anywhere with proper syntax
view raw gistfile1.txt This Gist brought to you by GitHub.

Learning Ruby [objects, classes and modules]

Monday, October 3rd, 2011

In Ruby pretty much everything is an object. Even classes and modules are objects. It gets rather confusing when you think that objects are instances of classes, yet a class is also an object. Fortunately, we don’t need to worry about this circularity. All we need know is that all of these entities are ultimately objects. This is a very important feature of Ruby that has many implications.

Here’s how you create an object from Ruby’s standard Object class:

my_object = Object.new
view raw gistfile1.rb This Gist brought to you by GitHub.

As in other object oriented languages, the behavior of an object is defined by its methods. An object has access to a large set of methods from the class of which it is an instance, and the super-classes and modules that are associated to that class. Classes serve as templates for the creating, or instantiating, objects.

All Ruby objects are descendants from the Object class. There are a few exceptions to this rule but for now we don’t need to worry about those (in part because I don’t know about those exceptions). From the Object class all objects and classes inherit a large number of methods. The functionality provided by these methods is quite powerful and is one of the characteristics that makes Ruby such a popular language; and why Ruby fans sometimes seem to border on fanatics.

Let’s take a look at an important method called initialize. This method acts like a constructor. It is called whenever an object is created. Like all Ruby methods, it can be defined to accept several input parameter. Unlike most Ruby methods, the initialize method is not called by using the keyword initialize but rather the keyword new.

Syntax for declaring the initialize method:

class MyClass
    def initialize(x)
        code to initialize stuff goes here
    end
end

view raw gistfile1.rb This Gist brought to you by GitHub.

One cool thing about Ruby is that since it is a dynamic scripting language, new functionality can be added or changed dynamically during runtime. These updates can be done to an individual object or to an object’s class.

Before I move on to discussing methods, let’s take a quick look at modules. Modules provide another way to bundle together methods and constants. They are often referred to as instance-less classes. In Ruby a class can only inherit from one class but it can mix-in several different module. Modules make it possible to share common functionality across multiple different classes, and support a modularity in Ruby programs.

One way to think about how modules and classes fit together is to consider that classes define types of object while modules define types of functionality. This is why classes usually have names that are nouns and modules often have names that are adjectives. For example, a class Car could mix-in a module called Steerable, which specifies how the object moves within a program’s virtual space.


Learning Ruby [table of contents]

Monday, October 3rd, 2011

I recently started to learn Ruby. Based on a friend’s recommendation I started this pursuit by reading and working through the book The Well-Grounded Rubyist, by David A. Black. This is a really great book. The descriptions and examples are straightforward and clear, and I’ve found it enjoyable to read. Ruby is also a really awesome language that has a bunch of useful and cool features.

As I’ve been going along I’ve been taking copious notes. This journal post will be updated regularly with to feature a current list of the topics I’ve covered in my notes. Not sure how helpful these will be to anyone else. If you are trying to learn Ruby from scratch I highly recommend David Black’s book that I mentioned earlier.

  1. Objects, Classes & Modules
  2. Methods & Message Handling
  3. Scope vs. Self, & Variables
  4. Conditional Control Structures
  5. Loops Control Structures
  6. Iterator Control Structures
  7. Error Handling Control Structures
  8. Syntactic Sugar
  9. Booleans, True, and False
  10. Symbols
  11. Arrays
  12. Hash Tables
  13. Sets
  14. Enumerable
  15. Enumerators
  16. IO System