Home
  Latest posts
  My Writings
  My Code
  My Gallery
  About me
 
  rssfeed Syndication
 
Bloggtoppen.se
 
 
Links
  Cornerstone
  SweNug
 
Post categories
  misc (48)
  Architecture (21)
  C# (19)
  Asp.Net (2)
  Vb.Net (2)
  Training (7)
  Data (19)
  Events (40)
  Platform (2)
  Orcas (4)
  Updates (3)
  Methods (10)
  Tools (6)
  Announcements (14)
  Languages (1)
  Patterns (6)
  Opinions (11)
  Fun (3)
  Ineta (1)
  Opinion (0)
  Practices (2)
  WCF (5)
 
 
 

Bringing a little bit of Ruby to C#

Saturday, March 03, 2007

The last couple of weeks I have been playing around with ruby and ruby on rails. I really like the natural flow of the syntax in the language and got inspired to bring parts of that to C#.

In ruby you can write iterations like this:

4.times do
   print "Yo!"
end

The above code snippet will execute "print "Yo!"" four times like a for statement. In addition to the simple times method there is also upto and step which will iterate to an upper bound and take other steps then +1. Have a look here http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html if you want to learn more about ruby expressions.

This syntax is really neat, I want it in my everyday coding?

In C# 3.0 we have the ability to extend types with "Extension Methods" technology. Since I liked this syntax so much I decided to extend Int to have similar functionality. My first attempt was to mimic the "times" syntax. The built in Func<> type requires a return type and since I just want to execute the code, not handle any result, I first needed a simple void() delegate:

public delegate void Func();

The extension method was then simple to implement:

public static void Times(this int ubound, Func codeBlockToExecute) {
    for ( int index = 0; index < ubound; index ++) {
         codeBlockToExecute.Invoke();
    }
}

(If you are unfamiliar to extension methods, this is good reading: http://www.interact-sw.co.uk/iangblog/2005/09/26/extensionmethods )

Now armed with this method we can utilize that the C# compiler handles numbers in text as integers by default and use our Times function:

5.Times(delegate { 
             Console.WriteLine("Yo!");
});

Not as beautiful as the original, the delegate keyword kind of takes away the grace a bit, but still functional enough. Using lambda it is possible to make it a bit more slick but not as flexible since lambda in C# only supports the execution of a single line of code, but still have a look at this:

5.Times( () => Console.WriteLine("Yo !"));

Attached to this post (you need to go to the website to get it) is the code for this and other ruby like extensions including the "step" and "upto" ones. The code is written and compiled on the Orcas march CTP.

Playing around with this and some other extension a bit I got a wish list for the C# team:

  • Func delegate with no return parameters (I know, I am lazy)
  • Extension Properties ( 5.Times.Do() would really be cool to do)
  • Handle {1,2,3} alone on a line as an array, so we could do {1,2,3}.foreach.do()

I guess I will pester the team about it when I get to Redmond in a couple of weeks.

kick it on DotNetKicks.com
Attached file: RubyLikeExtensions.zip
 

Comments
3/5/2007 5:14:00 PM     -   Will Sullivan
 
Yeesh. Some of the new language techniques that are being brought into C# are muddying the waters, imho. I know that they are in support of some of the cooler stuff (lamdas for LINQ (my captcha, ironically)), but if I ever have to support code written with a heavy reliance on some of this stuff.... as I said, yeesh. As Atwood just blogged recently, POO--Programming fOr Others--should be the neatest feature of your code.
 
3/5/2007 8:43:00 PM   http://judahgabriel.blogspot.com   -   Judah Himango
 
Extension methods are a little worrying. I've had to maintain C++ code that has #define preprocessors everywhere, and it's a crazy world, with hacking C++ into what looks like VB, or Ruby, or whatever the programmer was comfortable with...

Extension methods could "muddy the waters" as Will put it, although not to the degree #define allow in C. Extension methods means there are going to be functions on types that normally don't exist on those types. That's a little worrying.

People could code up an extension method to System.Object called IsNull:

object o = null;
bool isNull = o.IsNull();

At first glance, it would appear this should throw a NullReferenceException. But once one realizes IsNull is just an extension method, one then realizes it won't throw an exception. That is confusing. I hope people don't abuse it.
 
3/5/2007 10:33:00 PM     -   Andrew Norris
 
I don't think practices like these are inherently obfuscatory (though they can obviously be abused). Anything that can be used to make a language less verbose can, in principle, be used to clarify the language. The more (readable) code that fits on your screen at one time, the easier it is to see what the code is doing.

Instead, I think that as the language designers push things forward, we're going to have to develop new best practices for how to use these things effectively. Likewise, people who are used to what code looked like circa 1.1 will simply need to change to keep up.

The (admittedly verbose) anonymous methods in 2.0 can be one of the best features, and a good way to replace messy for-blocks with simpler aggregate functions. The new syntax is even better, because it makes the code more readable. I think extension methods will be like operator overloading: a godsend for certain limited cases, but poor practice to overuse.

BTW, something I think is even better than 5.Times( ... ) is

5.UpTo(10, (i) => Console.WriteLine(i));

Also, I love the idea of {1,2,3}.foreach.do(). An even more awesome related feature would be list comprehensions.
 
3/6/2007 1:56:00 PM   http://www.lowendahl.net   -   Patrik Löwendahl
 
Will:
This is the classic objection to aspects, dynamic features and general black box. Taking it to the extreme the same argument could be used against polymorphism as well.

Creating extesions that help you communicate your intentions based on your domain is what you call POO and that is what the DSL movement is all about. Being able to extend syntax this is way is nothing new and is even basis in small talk, nor is it going away. Quite the opposite, it will probably grow and instead of more generic features we will see "enabling features" to be help express your domain in code.
 
3/6/2007 1:57:00 PM   http://www.lowendahl.net   -   Patrik Löwendahl
 
Andrew:

I got some of thoose in my code samples attached to the post.
 
3/6/2007 1:58:00 PM   http://www.lowendahl.net   -   Patrik Löwendahl
 
Judah:

Yes, as all things we shouldn't over use them but there will be people who do :)
 
3/7/2007 10:36:00 AM     -   Roger Johansson
 
>>object o = null;
>>bool isNull = o.IsNull();

>>At first glance, it would appear this >>should throw a NullReferenceException.


I beg to differ.
Your statement _is true_ in the context of C#2

But as soon as extension methods are introduced, you can not use that mindset anymore.

If you are working with a language that support extension methods that can operate on null references , you cannot assume that calling mehtods on null references will throw an exception.

Why apply assumptions on a language where the assumptions no longer holds true?


Comment
Title:
Your name:
Your url:
Text:
Please enter the text from the image: