Learning Ruby

19 Jun 2013

Blog Ruby

I have been trying to learn a new language recently… Ruby. Ruby is a dynamic language created in the 90’s by Yukihiro “Matz” Matsumoto. I have been using C# and .Net for over 7 years, so moving to a dynamic language has been a bit of a mind shift but I have really enjoyed the journey so far.

Here are a few of the resources I have been using to aid my learning:

I just wanted to highlight a few things that I really like about the language…

Mutable Strings

Stings are mutable in Ruby! Now this could end up being a Gothca for me, as I’m so used to strings being immutable in .Net.

The following code, shows 2 objects being created; referenceToOriginalWord is equal to wordToMutate. I have then changed the value of the first character and added a character to the end of the original string, effectively updating the value from Hello to Yellow.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class MutableStrings
  def CanMutateAString
    wordToMutate = "Hello"
    referenceToOriginalWord = wordToMutate
 
    puts "BEFORE MUTATION ---> WordToMutate: " + wordToMutate
    puts "BEFORE MUTATION ---> referenceToOriginalWord: " + referenceToOriginalWord
 
    wordToMutate[0] = "Y"
    wordToMutate[5] = "w"
 
    puts "AFTER MUTATION ---> WordToMutate: " + wordToMutate
    puts "AFTER MUTATION ---> referenceToOriginalWord: " + referenceToOriginalWord
 
  end
end
 
testObject = MutableStrings.new
testObject.CanMutateAString

When can see from the output that the values after mutation for both the wordToMutate the referenceToOriginalWord variables have changed. Ruby has not created a copy of the value like in .Net.

Mutable Strings

Example in .Net

We can see that in C# if we try to change the character of a string at a particular position, we get a compiler error informing us that there is no setter (hence the immutable):

Mutable Strings

…and just for completeness the code below is a port of the Ruby example above, and you can see from the output that strings are immutable in C#.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Program
{
    static void Main(string[] args)
    {
        var wordToMutate = "Hello";
        var referenceToOriginalWord = wordToMutate;

        Console.WriteLine("BEFORE MUTATION ---> " + wordToMutate);
        Console.WriteLine("BEFORE MUTATION ---> " + referenceToOriginalWord);

        wordToMutate = wordToMutate.Replace("H", "Y");
        wordToMutate += "w";

        Console.WriteLine("AFTER MUTATION ---> " + wordToMutate);
        Console.WriteLine("AFTER MUTATION ---> " + referenceToOriginalWord);

        Console.Read();
    }
}

Mutable Strings

Mixins

I like how easy it is to do Mixins in Ruby… I struggled a while back to understand Mixins but had I of learnt about Mixins in Ruby first, I’m sure I would of picked it up a lot quicker! This code sample shows how you can extend the functionality of a class by mixing in a function from another module.

We start off with our class called ImGoodAtAdding. Now, if we wanted to, for some reason or another, extend our adding class to include subtracting functionality, we simply include that module in our class.

1
2
3
4
5
6
7
8
9
10
11
12
13
module SubtractingModule
  def Subtracting(number1, number2)
    number1 - number2
  end
end
 
 
class ImGoodAtAdding
  include SubtractingModule
  def Adding (number1, number2)
    number1 + number2
  end
end

When we instantiate a new instance of ImGoodAtAdding, we can now call the Subtracting method as well as the Adding method.

1
2
3
calculator = ImGoodAtAdding.new
puts calculator.Adding(2, 4)
puts calculator.Subtracting(2, 4)

Duck Typing

“If it looks like a duck, quacks like a duck and walks like a duck, it’s a duck”

right? …Wrong, not in Ruby.

Let’s look at the following example:

1
2
3
4
5
6
7
8
9
10
class DuckTyping
  def ThisShouldInTheoryTakeInANumber (number)
    puts "BEFORE ===> number is of type: " + number.class.to_s
 
    number = number * 2
    puts number
 
    puts "AFTER ===> number is of type: " + number.class.to_s
  end
end

Reading the code block above, gives me the impression that the number parameter should be a numeric value like an integer, and you can see from the code block below that when we instantiate a new Type of DuckTyping and invoke the ThisShouldInTheoryTakeInANumber method with the value 4 passed in, we get what we expect; the number 8 is printed along with the type of FixNum.

1
2
testing = DuckTyping.new
testing.ThisShouldInTheoryTakeInANumber 4

Duck Typing

So what happens when we pass in a string like "4"

1
2
testing = DuckTyping.new
testing.ThisShouldInTheoryTakeInANumber "4"

Duck Typing

Nothing ground breaking here, a string was passed in and although we applied a “mathematical” operation, it was still valid. What was returned here was the value "44" and a type of string. This is because the * operator has been overridden for the string type. We would get a compile error in .Net unless we created our own type and overrode the * operator ourselves.

This 3rd example shows just that, I have created a type called FooType and have overridden the * operator. All that is returned is 6. The interesting thing here is line 7 of the code below, I’m just passing in a new instance of the type to our DuckTyping instance.

1
2
3
4
5
6
7
8
class FooType
   def *(other)
     6
   end
end
 
testing = DuckTyping.new
testing.ThisShouldInTheoryTakeInANumber FooType.new

Duck Typing

Before the * operation occurred, the type was of type FooType as expected, but after the * it was of type FixNum… Magic!! …not really… What these 3 examples prove is that you can pass anything into the method in Ruby, it’s not type safe, hence why it’s called a dynamic language. In order to ensure your application behaves how you expect, some checking should happen to ensure the type your method receives is what is expected.