Showing posts with label IronRuby. Show all posts
Showing posts with label IronRuby. Show all posts

Thursday, February 27, 2014

Arrays and Indexers in IronRuby



Today's post is about Arrays and Indexers in IronRuby. Here below you will find a very easy to follow program, that demonstrate arrays and indexer, by implementing some simple tasks that will make you grasp the idea of those 2 features real quick. The main goal of this post, is not really teaching arrays because, come on, you probably already know "all" about them, in fact, it is more to show you how you do that in IronRuby, in this case, compared to all other 22 languages on future posts, which essentially, is the real aim behind this blog.

This is the last of the .NET dynamic languages. I'm considering to stop writing about it because the project seems to be dead with no updates since 13/03/11)... will see, probably this will be the last post about it if no news, fortunately, there is still JRuby.

By the way, if you missed my most recent post, "New Series - Arrays and Indexers", check it out. It has more details about the following program, and a bunch of definitions for the concepts used on this, and the following, posts. Or you can check my previous posts about arrays in JRuby, later on, just to compare.

I encourage you to copy the code below and try it yourself, normally, all programs you find in this blog are source code complete, just paste it on your IDE and run it.

There is room for improvement of the code, using generics is one example, but Generics, Collections, lambdas, etc. will have their own "series" of posts.


require "mscorlib" 
include System

# Console Program
def main()
    # Single-dimensional Array(s)
    print_title("Reverse Array Elements")
 
    # Declare and Initialize Array of Chars      
    letters = Array.new(5," ")
    letters[0] = "A"
    letters[1] = "E"
    letters[2] = "I"
    letters[3] = "O"
    letters[4] = "U"
 
    print_array(letters)  
    inverse_letters = reverse_char(letters)
    print_array(inverse_letters)

    print_title("Sort Integer Array Elements")
    # Declare and Initialize Array of Integers   
    numbers = [10, 8, 3, 1, 5]
    
    print_array(numbers)       
    ordered_numbers = bubblesort(numbers)   
    print_array(ordered_numbers)

    print_title("Sort String Array Elements")  
 
    # Declare and Initialize and Array of Strings 
    #names = Array.new(5, ["Damian","Rogelio","Carlos","Luis","Daniel"])
    # or just 
    names = ["Damian", 
      "Rogelio", 
      "Carlos", 
      "Luis", 
      "Daniel"]

    print_array(names)   
    ordered_names = bubblesort(names)   
    print_array(ordered_names)

    # Multi-dimensional Array (Matrix row,column)   
    print_title("Transpose Matrix")   

    # for an empty table initialized to 0s
    # matrix = Array.new(rows,0) { Array.new(cols,0) }
    matrix = [[6, 4, 24],      
              [1, -9, 8]]

    print_matrix(matrix)
    transposed_matrix = transpose_matrix(matrix)   
    print_matrix(transposed_matrix)  
 
    # Jagged Array (Array-of-Arrays)   
    print_title("Upper Case Random Array & Graph Number of Elements")   

=begin
# Creating an array of string arrays using the String.Split method   
# instead of initializing it manually as follows:   
# 
# text = [    
#  [ ["word1", "word2, "wordN"],    
#  [ ["word1", "word2, "wordN"],    
#  ...
#  ]   
#     
# Text extract from: "El ingenioso hidalgo don Quijote de la Mancha"        
=end
    text = [
    "Hoy es el dia mas hermoso de nuestra vida, querido Sancho;".split(" "),    
    "los obstaculos mas grandes, nuestras propias indecisiones;".split(" "),    
    "nuestro enemigo mas fuerte, miedo al poderoso y nosotros mismos;".split(" "),    
    "la cosa mas facil, equivocarnos;".split(" "),    
    "la mas destructiva, la mentira y el egoismo;".split(" "),    
    "la peor derrota, el desaliento;".split(" "),    
    "los defectos mas peligrosos, la soberbia y el rencor;".split(" "),    
    "las sensaciones mas gratas, la buena conciencia...".split(" ")
    ] 
 
    print_jagged_array(text)   
    uppercase_random_array(text)      
    print_jagged_array(text)   
    graph_jagged_array(text)

    # Array Exceptions
    print_title('Common Array Exceptions')
    
    print_common_array_exceptions(nil)
    print_common_array_exceptions(text)  

    # Accessing Class Array Elements through Indexer
    print_title('Alphabets')
    
    vowels = Alphabet.new(5)
    vowels[0] = "a"
    vowels[1] = "e"
    vowels[2] = "i"
    vowels[3] = "o"
    vowels[4] = "u"

    puts "\nVowels={%s}" % [vowels[0],vowels[1],vowels[2],vowels[3],vowels[4]].join(",")

    en = Alphabet.new("abcdefghijklmnopqrstuvwxyz")   

    puts "English Alphabet = {%s}" % [en]

    puts "Alphabet Extract en[9..19] = {%s}" % [Alphabet.new(en.slice(9, 10))]

    word1 = [en[6],en[14],en[14],en[3]].join("")
    word2 = [en[1],en[24],en[4]].join("")   
    word3 = [en[4],en[21],en[4],en[17],en[24],en[14],en[13],en[4]].join("")   

    puts "\n%s %s, %s!\n" % [word1, word2, word3]
 
    gets
end

def reverse_char(arr)
    arr.reverse
end 

def bubblesort(arr)  
    for i in arr.reverse
        for j in (0..arr.count-2)
            if arr[j] > arr[j + 1]    
                swap = arr[j]   
                arr[j] = arr[j + 1]   
                arr[j + 1] = swap   
            end    
        end 
    end   
    arr
end

def transpose_matrix(m)  
=begin
# Transposing a Matrix 2,3  
#     
#   A =  [6  4 24]T [ 6  1]  
#        [1 -9  8]  [ 4 -9]  
#                [24  8]  
=end
    transposed = Array.new(m[0].size) { Array.new(m.size) } 
    for i in 0..(m.size-1)   
        for j in 0..(m[0].size-1)   
            transposed[j][i] = m[i][j]
        end
    end
    transposed  
end

def uppercase_random_array(arr)      
    r = System::Random.new
    i = r.next(arr.size)
    for j in 0..(arr[i].size-1)   
        arr[i][j] = arr[i][j].upcase
    end
end

def print_array(arr)
    puts "\nPrint Array Content #{arr.GetType().Name}[#{arr.size}]"
    for i in 0..(arr.size-1)
        puts " array [%2s] = %2s" % [i, arr[i]]
    end
end

def print_matrix(m)
    puts "\nPrint Array Content #{m.GetType().Name}[#{m.size}][#{m[0].size}]"
    for i in 0..(m.size-1)
        for j in 0..(m[0].size-1)
            puts " array [%2s,%2s] = %2s" % [i, j, m[i][j]]
        end
    end
    m
end

def graph_jagged_array(arr)
=begin
# When using Arrays, we can use for(each) instead of for by index
#    for s in arr  
#        for w in s 
#        end
#    end
=end 
    puts "\nPrint Text Content #{arr.GetType().Name}"
    for i in 0..(arr.size-1)  
        line = ""
        line += "Line %2s|" % (i+1).to_s 
        for j in 0..(arr[i].size-1)   
            line += " * "
        end            
        line += "(#{arr[i].size})"
        puts line
    end
end

def print_jagged_array(arr)
    puts "\nPrint Jagged Array Content #{arr.GetType().Name}"
    for i in 0..(arr.size-1)
        line = ""
        for j in 0..(arr[i].size-1)     
            line += " " + arr[i][j]
        end
        if line == line.upcase
            line += " <-- [UPPERCASED]"
        end
        puts line
    end
end

def print_common_array_exceptions(arr)
    begin  
        arr.fetch(100)
    rescue Exception => ex
        puts "\nException: \n%s\n%s" % [ex.GetType().Name, ex.message]
    #else
    #   others
    end
end

def print_title(message)   
    puts ""  
    puts ("=" * 54)   
    puts message   
    puts ("=" * 54)
end     


class Alphabet
    # Array Field   
    @letters = []

    # Indexer Get/Set Property
    def [](idx)
        @letters[idx]
    end
    def []=(idx, value)
        @letters[idx] = value.upcase
    end
    
    # Read-Only Getter
    def length
        @letters.size
    end          

    # Constructor/Initializer
    def initialize(param)  
        if param.class == 1.class
            @letters = Array.new(param, " ")
        elsif param.class == "".class
            @letters = param.upcase.chars.to_a
        elsif param.class == [].class
            @letters = param
        else
            @letters = nil
        end
    end

    # Overridden Method    
    def to_s
        @letters.join(",")
    end
 
    # Method   
    def slice(start, length)
        @letters[start..start+length-1]
    end

end

main


The output:






















































































VoilĂ , that's it. Next post in the following days.

Sunday, July 17, 2011

Factorial and Fibonacci in IronRuby



Here below a little program in IronRuby that implements 2 classes. There is the main class, called Fiborial (Fibo(nnacci)+(Facto)rial) that implements the Fibonacci and the Factorial algorithms in two ways, one Recursive (using recursion) and the other Imperative (using loops and states). The second class is just an instance class that does the same thing, but its there just to show the difference between static and instance classes, and finally a main function called as module level code.

You can also find 3 more little examples at the bottom. One prints out the Factorial's Series and Fibonacci's Series, the second one just shows a class that mixes both: static and instance members, and finally the third one that uses different return types for the Factorial method to compare the timing and result.

As with the previous posts, you can copy and paste the code below in your favorite IDE/Editor and start playing and learning with it. This little "working" program will teach you some more basics of the Programming Language.

There are some "comments" on the code added just to tell you what are or how are some features called. In case you want to review the theory, you can read my previous post, where I give a definition of each of the concepts mentioned on the code. You can find it here: http://carlosqt.blogspot.com/2011/01/new-series-factorial-and-fibonacci.html 

WARNING: the code that you will see below is not following ruby guidelines/idiomatic coding, I did it in purpose to compare ruby's syntax and features side by side with other programming languages... For instance, instead of using a ruby bignum I imported and used System.Numerics.BigInteger instead. Other examples, naming convention and so on, so bear with me!

The Fiborial Program

# Factorial and Fibonacci in IronRuby
require "mscorlib"  
require "System"
require "System.Numerics"

include System::Collections::Generic
include System::Diagnostics
include System::Numerics
  
module FiborialRb
    # Static Class
    # static classes are not supported in Ruby
    class StaticFiborial
        # Static Field
        @@class_name = ""
        # no builtin static constructor/initializer support  
        # you can initialize field at this point and even add extra code         
        @@class_name = "Static Constructor"
        puts @@class_name
        # Static Method - Factorial Recursive
        def self.factorial_r(n)
            if n < 2
                BigInteger.One
            else
                BigInteger.Multiply(BigInteger.new(n), self.factorial_r(n - 1))                
            end
        end
        # Static Method - Factorial Imperative
        def self.factorial_i(n)
            res = BigInteger.One
            while n > 1
                res = BigInteger.Multiply(res, BigInteger.new(n))
                n -= 1
            end
            res
        end
        # Static Method - Fibonacci Recursive   
        def self.fibonacci_r(n)
            if n < 2
                1
            else
                self.fibonacci_r(n - 1) + self.fibonacci_r(n - 2)
            end
        end
        # Static Method - Fibonacci Imperative
        def self.fibonacci_i(n)
            pre = 1
            cur = 1
            tmp = 0
            for i in 2..n
                tmp = cur + pre
                pre = cur
                cur = tmp
            end
            cur
        end
        # Static Method - Benchmarking Algorithms
        def self.benchmark_algorithm(algorithm, values)
            timer = Stopwatch.new  
            i = 0
            testValue = 0    
            facTimeResult = BigInteger.Zero  
            fibTimeResult = 0           
            # "case/switch" Flow Control Statement
            case algorithm
            when 1
                puts "\nFactorial Imperative:"
                # "For in range" Loop Statement
                for i in 0..values.size - 1 do
                    testValue = values[i]                    
                    # Taking Time
                    timer.Start
                    facTimeResult = self.factorial_i(testValue)    
                    timer.Stop
                    # Getting Time
                    puts " (#{testValue}) = #{timer.Elapsed}"                    
                end
            when 2
                puts "\nFactorial Recursive:"
                # "While" Loop Statement
                while i < values.size do
                    testValue = values[i]
                    # Taking Time
                    timer.Start
                    facTimeResult = self.factorial_r(testValue)    
                    timer.Stop
                    # Getting Time
                    puts " (#{testValue}) = #{timer.Elapsed}"
                    i += 1
                end
            when 3
                puts "\nFibonacci Imperative:"
                # "until" Loop Statement
                until i == values.size do                    
                    testValue = values[i]
                    # Taking Time
                    timer.Start
                    fibTimeResult = self.fibonacci_i(testValue)    
                    timer.Stop
                    # Getting Time
                    puts " (#{testValue}) = #{timer.Elapsed}"
                    i += 1
                end
            when 4
                puts "\nFibonacci Recursive:"
                # "For each?" Statement
                values.each do |testValue|
                    # Taking Time
                    timer.Start
                    fibTimeResult = self.fibonacci_r(testValue)    
                    timer.Stop
                    # Getting Time
                    puts " (#{testValue}) = #{timer.Elapsed}"
                end
            else
                puts "DONG!"
            end
        end
    end
    
    # Instance Class
    class InstanceFiborial
        # Instance Field
        @class_name = ""
        # Instance Constructor/Initializer
        def initialize
            @class_name = "Instance Constructor"
            puts @class_name
        end
        # Instance Method - Factorial Recursive    
        def factorial_r(n)  
            # Calling Static Method    
            StaticFiborial::factorial_r(n)
        end
        # Instance Method - Factorial Imperative    
        def factorial_i(n)
            # Calling Static Method    
            StaticFiborial::factorial_i(n)    
        end
        # Instance Method - Fibonacci Recursive      
        def fibonacci_r(n)
            # Calling Static Method    
            StaticFiborial::fibonacci_r(n)    
        end
        # Instance Method - Fibonacci Imperative    
        def fibonacci_i(n)
            # Calling Static Method    
            StaticFiborial::fibonacci_i(n)
        end
    end
  
    # Console Program  
    puts "Static Class"    
    # Calling Static Class and Methods    
    # No instantiation needed. Calling method directly from the class    
    puts "FacImp(5) = #{StaticFiborial::factorial_i(5)}"
    puts "FacRec(5) = #{StaticFiborial::factorial_r(5)}" 
    puts "FibImp(11)= #{StaticFiborial::fibonacci_i(11)}" 
    puts "FibRec(11)= #{StaticFiborial::fibonacci_r(11)}" 
    
    puts "\nInstance Class"
    # Calling Instance Class and Methods    
    # Need to instantiate before using. Calling method from instantiated object    
    ff = InstanceFiborial.new
    puts "FacImp(5) = #{ff.factorial_i(5)}"
    puts "FacRec(5) = #{ff.factorial_r(5)}"
    puts "FibImp(11)= #{ff.fibonacci_i(11)}"
    puts "FibRec(11)= #{ff.fibonacci_r(11)}"
        
    # Create a (Ruby) list of values to test      
    # From 5 to 50 by 5    
    values = []
    for i in (5..50).step(5)
        values << i
    end

    # Benchmarking Fibonacci    
    # 1 = Factorial Imperative   
    StaticFiborial::benchmark_algorithm(1,values)
     # 2 = Factorial Recursive
    StaticFiborial::benchmark_algorithm(2,values)
    # Benchmarking Factorial    
    # 3 = Fibonacci Imperative 
    StaticFiborial::benchmark_algorithm(3,values)
    # 4 = Fibonacci Recursive 
    StaticFiborial::benchmark_algorithm(4,values)
    
    # Stop and exit  
    puts "Press any key to exit..."  
    gets  
end  

And the Output is:


































Humm, looks like Fibonnaci's algorithm implemented using recursion is definitively more complex than the others 3 right? I will grab these results for this and each of the upcoming posts to prepare a comparison of time execution between all the programming languages, then we will be able to talk about the algorithm's complexity as well.


Printing the Factorial and Fibonacci Series
require "mscorlib"  
require "System"
require "System.Numerics"

include System::Text
include System::Numerics
  
module FiborialSeriesRb    
    
    class Fiborial
         # Using a StringBuilder as a list of string elements  
         def self.get_factorial_series(n)
            # Create the String that will hold the list      
            series = StringBuilder.new    
            # We begin by concatenating the number you want to calculate      
            # in the following format: "!# ="      
            series.Append("!")
            series.Append(n)
            series.Append(" = ")
            # We iterate backwards through the elements of the series
            i = n
            while i >= 1
                # and append it to the list      
                series.Append(i)    
                if i > 1     
                    series.Append(" * ")      
                else
                    series.Append(" = ")    
                end
                i -= 1
            end
            # Get the result from the Factorial Method      
            # and append it to the end of the list      
            series.Append(self.factorial(n).to_s)
            # return the list as a string
            series.to_s
         end
         
         # Using a StringBuilder as a list of string elements
         def self.get_fibonnaci_series(n)
            # Create the String that will hold the list      
            series = StringBuilder.new
            # We begin by concatenating the first 3 values which      
            # are always constant
            series.Append("0, 1, 1")      
            # Then we calculate the Fibonacci of each element      
            # and add append it to the list      
            for i in 2..n    
                if i < n    
                    series.Append(", ")     
                else 
                    series.Append(" = ")
                end
                series.Append(self.fibonacci(i))
            end
            # return the list as a string      
            series.to_s  
         end
         
        def self.factorial(n)
            if n < 2
                BigInteger.One
            else
                BigInteger.Multiply(BigInteger.new(n), self.factorial(n - 1))                
            end
        end
        
        def self.fibonacci(n)
            if n < 2
                1
            else
                self.fibonacci(n - 1) + self.fibonacci(n - 2)
            end
        end
    end
    
    # Printing Factorial Series      
    puts ""    
    puts Fiborial::get_factorial_series(5)    
    puts Fiborial::get_factorial_series(7)    
    puts Fiborial::get_factorial_series(9)    
    puts Fiborial::get_factorial_series(11)    
    puts Fiborial::get_factorial_series(40)    
    # Printing Fibonacci Series      
    puts ""    
    puts Fiborial::get_fibonnaci_series(5)    
    puts Fiborial::get_fibonnaci_series(7)    
    puts Fiborial::get_fibonnaci_series(9)    
    puts Fiborial::get_fibonnaci_series(11)    
    puts Fiborial::get_fibonnaci_series(40) 
    
    # Stop and exit  
    puts "Press any key to exit..."  
    gets  
end

And the Output is:

















Mixing Instance and Static Members in the same Class Instance classes can contain both, instance and static members such as: fields, properties, constructors, methods, etc.
require "mscorlib"  

# Instance Class  
class Fiborial
    # Instance Field    
    @instance_count = 0
    # Static Field
    @@static_count = 0    
    # Instance Read-Only Getter
    def get_instance_count()     
        @instance_count    
    end    
    # Static Read-Only Getter
    def self.get_static_count()          
        @@static_count
    end    
    # Instance Constructor/Initializer
    def initialize()  
        @instance_count = 0
        puts "\nInstance Constructor #{@instance_count}"
    end
    # No Static Constructor/Initializer
    # You can do a self.initialize() static method, but it will not be called
    #def self.initialize()
    #    @@static_count = 0  
    #    puts "\nStatic Constructor #{@@static_count}"
    # Instance Method
    def factorial(n)  
        @instance_count += 1     
        puts "\nFactorial(#{n.to_s})"
    end
    # Static Method   
    def self.fibonacci(n)
        @@static_count += 1    
        puts "\nFibonacci(#{n.to_s})"
    end        
  
    # Calling Static Constructor and Methods      
    # No need to instantiate      
    Fiborial::fibonacci(5)    
        
    # Calling Instance Constructor and Methods      
    # Instance required      
    fib = Fiborial.new      
    fib.factorial(5)
  
    Fiborial::fibonacci(15)    
    fib.factorial(5)
        
    # Calling Instance Constructor and Methods      
    # for a second object      
    fib2 = Fiborial.new   
    fib2.factorial(5)    
        
    puts ""
    # Calling Static Getter    
    puts "Static Count = #{Fiborial::get_static_count}" 
    # Calling Instance Property of object 1 and 2      
    puts "Instance 1 Count = #{fib.get_instance_count}"
    puts "Instance 2 Count = #{fib2.get_instance_count}"
        
    gets
end

And the Output is:

















Factorial using int, float, System.Numerics.BigInteger
So, it looks like integers in python can hold big integers, so using (Iron)Ruby int/long or System.Numerics.BigInteger is the same so not much to say here. NOTE: as with the previous scripts you need to manually add a reference to the System.Numerics.dll assembly to your project   or SearchPath + require  so you can add it to your code.

require "mscorlib"
require "System"
require "System.Numerics.dll"

include System::Numerics
include System::Diagnostics
    
# Int/Long Factorial    
def factorial_int(n)
    if n == 1
        1.to_i
    else    
        (n * factorial_int(n - 1)).to_i
    end
end
# double/float Factorial
def factorial_float(n)
    if n == 1  
        1.0
    else
        (n * factorial_float(n - 1)).to_f
    end
end
# BigInteger Factorial       
def factorial_bigint(n)
    if n == 1  
        BigInteger.One
    else          
        BigInteger.Multiply(BigInteger.new(n), factorial_bigint(n-1))  
    end
end

timer = Stopwatch.new
facIntResult = 0  
facDblResult = 0.0    
facBigResult = BigInteger.Zero  
i = 0    
        
puts "\nFactorial using Int/Long"
# Benchmark Factorial using Int64      
for i in (5..50).step(5)
    timer.Start 
    facIntResult = factorial_int(i)
    timer.Stop
    puts " (#{i.to_s}) = #{timer.Elapsed} : #{facIntResult}"
end
puts "\nFactorial using Float/Double"
# Benchmark Factorial using Double
for i in (5..50).step(5)
    timer.Start    
    facDblResult = factorial_float(i)    
    timer.Stop
    puts " (#{i.to_s}) = #{timer.Elapsed.to_s} : #{facDblResult.to_s}"
end        
puts "\nFactorial using BigInteger"    
# Benchmark Factorial using BigInteger    
for i in (5..50).step(5)
    timer.Start
    facBigResult = factorial_bigint(i)
    timer.Stop
    puts " (#{i.to_s}) = #{timer.Elapsed.to_s} : #{facBigResult.to_s}"
end

gets

And the Output is:


Monday, October 25, 2010

IronRuby - Basics by Example



Continue with the Basics by Example; today's version of the post written in IronRuby Enjoy!

You can copy and paste the code below in your favorite IDE/Editor and start playing and learning with it. This little "working" program will teach you the basics of the Programming Language.

There are some "comments" on the code added just to tell you what are or how are some features called. In case you want to review the theory, you can read my previous post, where I give a definition of each of the concepts mentioned on the code. You can find it here: http://carlosqt.blogspot.com/2010/08/new-series-languages-basics-by-example.html 


Greetings Program - Verbose
# IronRuby basics
require 'mscorlib'

module RbGreetProgram
    class Greet
        # Fields or Attributes
        @message = ""
        @name = ""
        @loopMessage = 0
        # Properties | Getters, Setters
        def message
          @message
        end
        def message=(val)
          @message = capitalize(val)
        end
        def name
          @name
        end
        def name=(val)
          @name = capitalize(val)
        end
        def loopMessage
          @loopMessage
        end
        def loopMessage=(val)
          @loopMessage = val
        end
        # Constructor or Initializer Method
        def initialize
            @message = ""
            @name = ""
            @loopMessage = 0
        end
        # Overloaded Constructor
        # No Overloaded Constructors/Initializers Support in Ruby
        # Method 1
        def capitalize(val)
            # "if-then-else" statement
            if val.length >= 1
                return val.capitalize
            else
                return ""
            end
        end
        private :capitalize
        # Method 2
        def salute
            # "for" statement
            for i in 0..@loopMessage
                puts "#@message #@name!"
            end
        end
        # Overloaded Method
        # No Overloaded Methods Support in Ruby. New methods instead.
         # Method 2.1
        def salute21(message, name, loopMessage)
            # "while" statement
            i = 0
            while i < loopMessage do
                puts "#{capitalize(message)} #{capitalize(name)}!"
                i += 1
            end
        end
        # Method 2.2
        def salute22(name)
            # "switch/case" statement
            dtNow = System::DateTime.Now
            @message = case dtNow.Hour
                when 6..11 then "good morning,"
                when 12..17 then "good afternoon,"
                when 18..22 then "good evening,"
                when 23,0..5 then "good night,"
                else "huh?"
            end
            puts "#{capitalize(@message)} #{capitalize(name)}!"
        end
    end

    # Console Program
    # Define variable object of type Greet
    # Instantiate Greet. Call Constructor
    g = Greet.new
    # Call Set Properties
    g.message = "hello"
    g.name = "world"
    g.loopMessage = 5
    # Call Method 2
    g.salute()
    # Call Method 2.1 and Get Properties
    g.salute21(g.message, "ironRuby", g.loopMessage)
    # Call Method 2.2
    g.salute22("carlos")
    # Stop and exit
    puts "Press any key to exit..."
    gets
end
__END__

Greetings Program - Minimal
# IronRuby basics
class Greet
    # Fields or Attributes
    @message = ""
    @name = ""
    @loopMessage = 0
    # Properties | Getters, Setters
    def message
      @message
    end
    def message=(val)
      @message = capitalize(val)
    end
    def name
      @name
    end
    def name=(val)
      @name = capitalize(val)
    end
    def loopMessage
      @loopMessage
    end
    def loopMessage=(val)
      @loopMessage = val
    end
    # Constructor or Initializer Method
    def initialize
        @message = ""
        @name = ""
        @loopMessage = 0
    end
    # Overloaded Constructor
    # No Overloaded Constructors/Initializers Support in Ruby
    # Method 1
    def capitalize(val)
        # "if-then-else" statement
        if val.length >= 1
            return val.capitalize
        else
            return ""
        end
    end
    private :capitalize
    # Method 2
    def salute
        # "for" statement
        for i in 0..@loopMessage
            puts "#@message #@name!"
        end
    end
    # Overloaded Method
    # No Overloaded Methods Support in Ruby. New methods instead.
    # Method 2.1
    def salute21(message, name, loopMessage)
        # "while" statement
        i = 0
        while i < loopMessage do
            puts "#{capitalize(message)} #{capitalize(name)}!"
            i += 1
        end
    end
    # Method 2.2
    def salute22(name)
        # "switch/case" statement
        dtNow = System::DateTime.Now
        @message = case dtNow.Hour
            when 6..11 then "good morning,"
            when 12..17 then "good afternoon,"
            when 18..22 then "good evening,"
            when 23,0..5 then "good night,"
            else "huh?"
        end
        puts "#{capitalize(@message)} #{capitalize(name)}!"
    end
end

# Console Program
# Define variable object of type Greet   
# Instantiate Greet. Call Constructor   
g = Greet.new
# Call Set Properties   
g.message = "hello"     
g.name = "world"     
g.loopMessage = 5
# Call Method 2     
g.salute()   
# Call Method 2.1 and Get Properties     
g.salute21(g.message, "ironRuby", g.loopMessage)   
# Call Method 2.2
g.salute22("carlos")
# Stop and exit     
puts "Press any key to exit..."
gets


And the Output is:




















Where to define Class Fields/Attributes in (Iron)Ruby

puts "Class Attributes Example:"
class ClassAttributes
    # You do not need to explicitly add the Fields/Attributes as shown below within the class:
    # message = ""
    # name = ""
    # loopMessage = 0
 # because they are added to the class as Fields/Attributes the first time they appear in
 # your code. For example, here below, in the Initialize method,
 # we have 2 fields (name and message)
 def initialize
        @message = "message" # class field
        @name = "name"  # class field
 end
 # and one more within a public method (loopMessage)
 def salute
  @loopMessage = 1 # class field
  localtest = 0   # local variable  
  puts "#@message, #@name, #@loopMessage"
 end
end

# Then, you can access each of them as you normally do:
f = ClassAttributes.new
f.salute

Auto-Implemented Properties in (Iron)Ruby
Auto-implemented properties enable you to quickly specify a property of a class without having to write code to Get and Set the property. The following code shows how to use them just like with VB.NET, C#, C++/CLI and so on.

puts ""
puts "Auto-Implemented Properties Example:"
# Ruby basics
class Greet
    # Fields or Attributes
    #@message = ""
    # Manual Properties | Getters, Setters
    #def message
    # @message
    #end
    #def message=(val)
    #  @message = capitalize(val)
    #end
    
    # Instead of creating a field and a manual property (as above)
    # we use the attributes syntax to create our Auto-Implemented Property
    # that will be linked to our @message class field/attribute
    attr_accessor :message
    # you can also create read or write only props using attr_writer|attr_reader
    
    def initialize
        @message = ""
    end
    def salute
        puts "#@message"
    end
end

g = Greet.new
# we set the value of message through our write property
g.message = "hola ruby"
g.salute
# or get the value from it as well
puts g.message

Overloading Constructor and Methods in (Iron)Ruby

Ruby does not support Overloading Methods nor Constructors, instead, you can define one method with variable arguments and code the if-elseif code to handle both(or multiple) cases yourself.

puts ""
puts "Overloaded-like Constructor and Method Example:"
class Overloading
    # Constructor with variable arguments
    def initialize(*args)
        # if args list/sequence is not empty we use the arguments,
        # otherwise we use the class fields
        if args.size > 0
            @message = args[0]
            @name = args[1]
            @loopMessage = args[2]
        else
            @message = 'empty_message'
            @name = 'empty_name'
            @loopMessage = 2
        end
    end
    # Method  with variable arguments
    def salute(*args)
        # if args list/sequence is not empty we use the arguments,
        # otherwise we use the class fields
        if args.size > 0
            for i in 1..args[2]
                puts "#{args[0]}, #{args[1]}!"
            end
        else
            for i in 1..@loopMessage
                puts "#@message, #@name!"
            end
        end
    end
end

# and now we use the "overloaded-like" constructor and method
# calling constructor without parameters
o1 = Overloading.new
# calling method without parameters
o1.salute
# calling method with parameters
o1.salute("Hello", "IronRuby", 3)
# calling constructor with with parameters
o2 = Overloading.new("Hello", "Carlos", 2)
# calling method without parameters
o2.salute


And the Output is:


Saturday, June 26, 2010

OO Hello World - IronRuby



Let’s have a look at the hello world program in IronRuby; another language implemented to run on the DLR runtime.

By the way, you can see my previous post here: http://carlosqt.blogspot.com/2010/06/oo-hello-world.html
where I give some details on WHY these "OO Hello World series" samples.

Version 1 (Minimal):
The minimum you need to type to get your program compiled and running.
class Greet
 @name = ""
 def initialize(name)
  @name = name.capitalize
 end
 def salute
  puts "Hello #@name!"
 end
end

# Greet the world!
g = Greet.new("world")
g.salute


Version 2 (Verbose):
Explicitly adding instructions and keywords that are optional to the compiler.
require "mscorlib"

module GreetProgram 
 class Greet
  @name = ""
  def initialize(name)
   @name = name.capitalize
  end
  def salute
   puts "Hello #@name!"
  end
 end
 
 # Greet the world!
 g = Greet.new("world")
 g.salute  
end


The Program Output:










IronRuby Info:
“IronRuby is an Open Source implementation of the Ruby programming language for .NET, heavily relying on Microsoft's Dynamic Language Runtime.” Taken from: (http://www.ironruby.net/)

Appeared:
2007
Current Version:
Developed by:
John Lam + DLR Team
Creator:
John Lam
Influenced by:
Ruby (Yukihiro Matsumoto)
Predecessor Language
RubyCLR?
Predecessor Appeared
2006
Predecessor Creator
John Lam
Runtime Target:
DLR
Latest Framework Target:
4.0
Mono Target:
Yes
Allows Unmanaged Code:
No
Source Code Extension:
“.rb”
Keywords:
38
Case Sensitive:
Yes
Free Version Available:
Yes
Open Source:
Yes
Standard:
No
Latest IDE Support:
SharpDevelop 3.2/4.0 (beta)
Language Reference:
Extra Info: