5.times("hello") in C#

(This post is an old article I wrote on Google Knol. I have shifted it here... Witness the power of Extension Methods)
My meeting with Dalpat ...

I happened to meet a Ruby Language enthusiast (Mr. Dalpat) recently. He was showing me some cool programming tricks in Ruby Language. He was bullish about power of Ruby and lamented over limitations of C# and Java. "C#(especially after version 3.0) has a bigger toolbox of idioms than Java , but Ruby is far better" he said.

Ruby being dynamic and capable of supporting internal DSL's( Domain Specific Language) has always had my due respect. However, I wanted to know what made this Ruby evangelist so strongly opinionated. One of the things that came up in his praise for Ruby was that even literals in Ruby were objects. So one could very naturally write something like 

5.times{puts "Hello"}

and print Hello five times.  This he said was possible because the times method had already be defined in Ruby's Integer class. "It's impossible to do such things in C# or Java" he said. I started thinking... was it really impossible?

   
In Search of Solution ...

 I want to say  5.times("Hello") ;                                                                                                                
And this will print hello 5 times on Console                                                                                                   

Generally in a statically typed language most of the translation activities like name resolution and binding are performed before runtime. Typically, conformance to language rules are checked before the program runs, and this give a degree of assurance that the program is well-behaved. However, this also means that there is a reduced degree of freedom at runtime. In statically typed languages its not easy to add a new method to an object at runtime. To add a method to an object at runtime would amount to type mutation. Type validations are done before runtime and type mutation is not normally allowed at runtime. In dynamic languages it is possible to add a method to an instance or a class at runtime. Dynamic language translators can allow greater degree of freedom to program logic, as they have access to runtime context. C# is a statically typed language and the literal 5 is an instance of type Int32. There is no method named Times in Int32. So how can  I possibly invoke Times on literal 5? Can I add Times method to Int32 ? Using inheritance is not an option here. I wantTimes method to appear as a method in type Int32 and not as a method in its subtype.



The Solution ...  Extension Method      


We can add a method to a type in C# using extension method. So I tried to add Times method to Int32.
The following class defines the extension method Times. It's first parameter indicates the type to which it can be applied.



Program ...  FiveTimesSimple



/*** The following program uses the extension method to exhibit Ruby like functionality. ***/ 




using System;


namespace FiveTimesSimple
{
    class Program
    {
        static void Main(string[] args)
        {
            5.Times("Hello");
            10.Times("bye");
            Console.ReadLine();
        }
    }
    static class IntegerUtility
    {
        public static void Times(this Int32 i, String str)
        {
            for (int j = 0; j < i; j++)
            {
                Console.WriteLine(str);
            }
        }
    }
}



Output of program    FiveTimesSimple ...

Hello
Hello
Hello
Hello
Hello
bye
bye
bye
bye
bye
bye
bye
bye
bye
bye



In Search of  Concurrent Solution ...

What if the job is to be done 5 times concurrently !!! . Given a unit of work to be performed, we want 5 thread to be invoked and each thread assigned a work unit. The work unit can be printing hello on console. (Trivial I understand, but it could be easily any other complex work). 

I want to have a statement like.
5.TimesCon( << unit of work >>); 





Program ... FiveTimesConcurrent 




using System;

using System.Threading;

namespace FiveTimesConcurrent
{
    
    class Program
    {
        static void Main(string[] args)
        {
            
            5.Times("Hello");
            10.Times("bye");
            5.TimesCon(s=>Console.WriteLine("Hello says "+ s));
            10.TimesCon(s=>Console.WriteLine("Bye says " + s));
            Console.ReadLine();
        }
    }
    
    
    static class IntegerUtility
    {
        public static void Times(this Int32 i, String str)
        {
            for (int j = 0; j < i; j++)
            {
                Console.WriteLine(str);
            }
        }
        public static void TimesCon(this Int32 i, ParameterizedThreadStart ts)
        {
            
            for (int j = 0; j < i; j++)
            {
                new Thread(ts).Start("Thread" + j);
            }
        }
    }
}





Ouput of  Program FiveTimesConcurrent ...


Hello

Hello
Hello
Hello
Hello
bye
bye
bye
bye
bye
bye
bye
bye
bye
bye
Hello says Thread1
Hello says Thread0
Hello says Thread2
Hello says Thread3
Hello says Thread4
Bye says Thread0
Bye says Thread2
Bye says Thread1
Bye says Thread3
Bye says Thread4
Bye says Thread6
Bye says Thread5
Bye says Thread7
Bye says Thread8
Bye says Thread9



Dalpat can't believe his eyes ...
           
Dalpat found it difficult to believe when I suggested the aforementioned solution. However, he argued that it was verbose when compared to Ruby. I was not in an argumentative mood, in-fact I was full of appreciation for features like extension methods and lambda functions in C#. Although very simple , the above code helped me express a Ruby idiom in C#. I am looking forward to express and simulate more complex idioms. I thanked Dalpat for getting me started in this interesting journey.



Program ... PassingCodeBlocks 
Passing Code Blocks as requested by Kunal Modi(see comments)         

   Idioms and Patterns used in the Program 

  • Visitor Pattern ( for a Literal )

You can pass a code block (lambda) to a literal and the code block operates on the literal. This is a         instance of  Visitor Pattern. Here the code block is the visitor visiting the literal.
e.g.     5.Inject(x => x * x);

  • Range ( e.g. 1..10 )

You don't have direct support for range in C# . Here the Ruby's range idiom has been implemented using an array. I have considered only positive ranges for simplicity. Extending it for all possible ranges and types would be an interesting exercise.   
e.g       1.Range(5).Sum();


  • Visitor Pattern ( for a Range)

You can pass a code block to a range. The code block will work on the range and return some result.
5.Range(10).Inject((a) => { int x = 0; foreach (int i in a) { x = x + i; } return x; });This again is an instance of Visitor pattern , but applied to a range.

This implementation can be made more sophisticated. Also  a lot more can be harnessed from .Net collection API. However, I have kept it simple enough to be able to illustrate the point. You can chain the visitors on a given range if the return type of Injection is changed to that of an array. That would be an interesting exercise to try.  
   

namespace CodeBlock
{
    
    class Program
    {
        
        static void Main(string[] args)
        {
            /* Injecting logic to print itself */
            5.Inject(x => { Console.WriteLine(x); return x; });
            
            /* Injecting logic to calculate square */
            5.Inject(x => x * x);

            /* Chaining Injection */
            10.Inject(x => x * x).Inject(x => x * 2).Inject(x => { Console.WriteLine(x); return x; });
            
            /* Injecting logic in a range */
            5.Range(10).Inject((a) => { int x = 0; foreach (int i in a) { x = x + i; } return x; });
            
            /* Simplified injection by creating special method sum */
            int sum = 1.Range(5).Sum();
            Console.WriteLine("sum = " + sum);
            
            /* Adding numbers in the range and printing*/
            3.Range(8).Sum().Inject(x => {Console.WriteLine(x); return x; });

            4.Range(7).Max().Print();
           
            Console.ReadLine();
        }
        
    }
    static class IntegerUtility
    {
        public static Int32 Inject(this Int32 i,Func<Int32,Int32> p)
        {
           return  p(i);
        }
        public static Int32[] Range(this Int32 i,int j)
        {
            int size = j - i + 1;
            Int32[] list = new Int32[size];
            for (int k = 0 ; k < size; k++)
            {
                list[k] = i++;
            }
            return list;
        }
        public static int Inject(this Int32[] i ,Func<Int32[],Int32> p)
        {
            return p(i);
        }
        public static int Sum(this Int32[] i)
        {

            return i.Inject((a) => { int x=0; foreach (int j in a) { x = x + j; } return x; });
        }
        public static string Print(this Int32 i)
        {
            Console.WriteLine(i.ToString());
            return i.ToString();
        }
    }
}

Ouput of  Program PassingCodeBlock ...

5
200
sum = 15
33
7




Program ... PythonStringMultiplication 
Simulating Python's string multiplication as requested by John Morrison(see comments)                       


I have tried to address the Python idiom in two ways. One is adding extensions to String class as illustrated in  scenario 4, 5 and 6 . Second is adding extensions to Int32 class as illustrated in scenario 1,2 and 3.  



namespace Simulating_Python
{
    class Program
    {
        static void Main(string[] args)
        {
            
            // scenario 1    
            //equivalent to >>> 5 * "Hello"
            Console.WriteLine("\nScenario1");
            
            string s = 5.@p("Hello");
            Console.WriteLine(s);

            // scenario 2  
            //equivalent to >>> print 5 * "Hello"
            Console.WriteLine("\nScenario2");

            5.@p("Hello").print();

            // scenario 3
            //equivalent to >>> print 3 * (5 * "Hello" )
            Console.WriteLine("\nScenario3");

            3.@p(5.@p("Hello")).print();

            // scenario 4 
            //equivalent to >>> "Hello" * 5
            Console.WriteLine("\nScenario4 \nnothing to be displayed");
            
            "Hello".x(5);

            // scenario 5 
            // equivalent to >>> print 5 * "Hello"
            Console.WriteLine("\nScenario5");

            "Hello".x(5).print();

            // scenario 6
            //equivalent to >>> print ("Hello" * 5) * 3 
            Console.WriteLine("\nScenario6");

            "Hello".x(5).x(3).print();

            Console.ReadLine();
        }
    }

    static class IntegerUtility
    {
        public static string @p(this Int32 i, string s)
        {
            string temp=null;
            for (; i > 0; i--) { temp += s; }
            return temp;
        }
        public static string print(this string s)
        {
            Console.WriteLine(s);
            return s;
        }
        public static string x(this String s, Int32 i)
        {
            string temp = null;
            for (; i > 0; i--) { temp += s; }
            return temp;

        }
    }
}


Ouput of  Program PythonStringMultiplication ...


Scenario1
HelloHelloHelloHelloHello

Scenario2
HelloHelloHelloHelloHello

Scenario3
HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello

Scenario4
nothing to be displayed

Scenario5
HelloHelloHelloHelloHello

Scenario6
HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello






Comments

Fantastic application of c# to beat Ruby

Fantastic application of c# to beat Ruby.This is great exercise and article to know how deep knowledge/research of C# environment and compiler is been done by you.
Will C# be taking up Ruby market ?


Last edited Mar 17, 2010 1:21 AM



John Morrison

How about Python??

print "hello"*5


Last edited Mar 15, 2010 9:09 AM

Dalpat

Hi Sir,

Really very nice and helpful post .. and yes I still remember Dalpat is you fav :).

I think which language is good is very subjective topic, one should focus what he want to develop (project) and then need to decide which is better language to use ... rather then going into market for the fav language ..

regards,
Rushabh


Last edited Mar 15, 2010 12:17 AM


Can code blocks be passed into statically typed languages

Nice one Sir, But let me play Dalpat's role here.
The notion of primitives being objects is so exciting. I would love to see if C#/Java can handle code blocks if passed to it. For instance the following code block

5.times{|x| puts "this code block can be executed " + x.to_s + " times" }

or another trivial one which calculates the sum of x consecutive numbers like

(1..10).inject{|sum,number| sum+number}

I miss these notions in statically types languages. I believe this can definitely be integrated into them, but at end of the day having something out of the box is pretty cool
As of now I am not too sure of Ruby's threading model. Will comment on it soon.

Let me know if I can make your journey more interesting. :)


Last edited Mar 14, 2010 9:10 AM



Comments

Popular posts from this blog

Harikavach ( Level 3 )

Potter Metaphor.

Grapes a Metaphor