C# 3 is like a Moped

When I was growing up I used to occasionally hear the saying “a Moped is just fast enough to get you into trouble, but not fast enough to get you out of trouble.” I have no idea where it came from, and never saw a single Moped until my twenties, but it’s an ideal way to describe something I was feeling this week. We’re trying to do some language oriented programming in our new project with C# 3, and that generally means Fluent Interfaces. We’re getting some real benefits out of our approach, but the fluent interface code itself can become completely opaque when it devolves into “generics hell” like this:

The API using this code is okay and generally pretty usable, but pain accrues when it’s time to extend the Fluent Interface.

C# 3 is great, and I’m glad to have it, but the new language features apparently have their limitations. You can drive out more code reuse with generics and lambda expressions, but the readability eventually collapses when you push it too hard. We’re backing up and writing more lines of explicit code instead of trying so hard with generics.

A couple years back there was a blog meme floating around called Is Ruby an Acceptable Lisp? When C# 3 came out, there was some quiet discussion in ALT.NET circles that maybe the new language features (the “var” keyword, better type inference, lambdas) would be enough to satisfy us in regards to Language Oriented Programming and keep us from clamoring for Ruby. The answer for me after three months of hands on C# 3 is that C# 3 is NOT an acceptable Ruby. Simply having Duck Typing (or maybe the super type inference that OCaml and other exotic languages have) would have made what we were trying to do easier to code and easier to read. Some of the Fluent Interface work helps to boil down code into a much smaller surface area, but there’s still too many extraneous angle brackets, squiggley brackets, and semicolons floating around to make it really readable the same way that a Ruby or Python internal DSL can be. Maybe my entire point here is that C# is simply not Ruby and we shouldn’t try so hard to use C# like Ruby.

So, anybody know any new news on IronRuby?

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.

I can’t argue that Ruby is more popular than Boo, but I can’t think of something that I can do in Ruby that i can’t in Boo, and I can certainly think about it the other way around.
Do you have any concrete example?

http://flimflan.com/blog Joshua Flanagan

If you haven’t yet, spend at least a weekend programming in Boo. For someone that has been “thinking C#” for a few years, I think it is much easier to jump into and be immediately productive with Boo as compared to Ruby.

http://dotnet.agilekiwi.com/blog/2006/10/shorthand-interfaces.html John Rusk

I knew you’d pop in here sooner or later. I think that Ruby has a far richer existing ecosystem and a bigger community than Boo. I know that you really like Boo, but it’s basically Ayende on one side versus hundreds of other people for Ruby. Boo is interesting, but I think I don’t think it ever makes the mainstream if IronRuby really takes off. Besides, I’m already using Ruby for little tasks and like the language.

And I think you’re getting it backwards in terms of language oriented features, which is what I’m really wanting here. From the examples and literature I’ve seen Boo is not as expressive as Ruby and doesn’t have nearly the same metaprogramming abilities.

http://Csaba.Urbaniczky@Hotmail.com Csaba

Hi,

You should look at the Cobra language.
Best of Pyton with static and duck typing in .NET and more!!!!!

Jeremy,
This is not the first time you stated that you are waiting for IronRuby.
Is there a reason for this?
Boo is here, stable, and has more language oriented features than Ruby.
And reason you are not exploring that?

http://www.ejstembler.com Edward J. Stembler

@Jeremy: I think convergance is simply the natural progression here. Recently, we saw C# 3.0 gain some features traditionally found in dynamic languages. The next version, 4.0, is gaining dynamic lookup.

It’s not difficult to imagine a language/compiler combination, in the not too distant future, which could gracefully embrace both worlds. Granted, this environment should be architected from from the ground-up. Not something which is added on as an after thought to an existing system with existing limitations.

http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

@Edward,

I don’t see convergence as a good idea. Let’s do polyglot programming and have languages that are simpler to do one thing very well instead of one size fits none languages. Do you really think a language with both fullblown, compiler enforced Design By Contract *and* dynamic typing/open classes/metaprogramming is possible without collapsing under its own weight?

http://www.ejstembler.com Edward J. Stembler

@ Mike: I agree, we’ll likely see a polyglot phase before and on the way towards the ultimate convergance.

http://blowmage.com/ Mike Moore

@Edward More to your point about language convergance: I think we won’t see languages converge as much as we see different languages cooperate well together. This is the promise of putting the DLR on top of the CLR, and adding new languages to the JVM.

I think there _will_ continue to be discussions about dynamic vs. static, and compiled vs. interpreted, but those will be discussions about _which_ language to use to solve the problems in a particular “tier” of the application. This is the Polyglot Programming model.

http://blowmage.com/ Mike Moore

@Edward You raise an interesting point about C#’s evolution to a hybrid language. I agree we will see the lines blur between languages, but not in the ways we might always want. I actually had a somewhat viral blog conversation about this.

It seems C# is slowing evolving into a hybrid language. However, I cannot help but to wonder: At what point is it better to consider a different approach?

For instance, while it’s true you can hack your way around many of C#’s language-imposed limitations (i.e. IoC, DI, Providers, plugins, duck typing et. al.). Those types of solutions usually work against the gain of the original intent of the (C#) language. They also add additional complexities and dependencies to your code base. Whereas they are usually non-issues in dynamic languages such as Python or Ruby. I’m not suggesting that dynamic languages are the end-all-be-all solution for everyone’s needs. However they are less prone to certain (static) design issues, and more conducive to flexibility.

In any case, I think a few years from now we’ll see a convergance of sorts. We’ll be able to benefit from both worlds. There won’t be discussions about dynamic vs. static, or compiled vs. interperted…

http://neilmosafi.blogspot.com Neil Mosafi

Hey wekempf good point – I didn’t know you write using aliases with generic types, that is quite useful, thanks.

It’s not quite the same as with a typedef in C++, where you are actually exposing the type through the usage of your class/namespace to other classes which may use it. still good

http://wekempf.spaces.live.com wekempf

@Neil
C# does have that feature.

using StringIntDictionary = System.Collections.Generic.Dictionary;

http://www.codethinked.com Justin Etheredge

@Jeremy Miller – John Lam said at Mix that they wanted to have a non-trivial Rails app running on IronRuby by RubyConf (which is pretty soon, so I have no idea of that is going to happen), but that they expected to hit 1.0 in about a year. It was actually pretty interesting to hear him talking about the challenges of developing the DLR version of a language that has no spec, and how much testing and prodding they are having to do in order to fish out the runtime behavior of performing certain tasks. Hopefully IronRuby will be something that Microsoft will pursue whole heartily, as there certainly are a lot of tasks that Ruby is much better suited for than C#, and vice versa.

http://blowmage.com/ Mike Moore

@Christopher A language-to-task analysis is a great idea for a blog post. I’ll add it to the pile of things I want to do but am behind on.

http://www.bluespire.com/blogs Christopher Bennage

@Jeremym @Moore
What I’d like to read is a “language to task” analysis. By that I mean, what is C# good for? What is Ruby good for? What is Boo good for? Python, OCaml, etc.
If I’m to be a polyglot (and for inexplicable reasons I’m compelled to be), I need to know this.
I’ve heard things like, but they are still too vague for me:
OCaml is good for writing compilers. Boo is good for crafting DSL’s. C# is good for enterprisey things (whatever that means). F# is good for analysis (or the same things as OCaml). Ruby is just good.

I’m currently learning Ruby and Boo, but I don’t know enough yet to answer these questions for myself. Maybe in a few months…

http://blowmage.com/ Mike Moore

@Edward For me, the difference between duck typing and static compile time checking boils down to this: Static languages (like C#/Java) implement polymorphism though inheritance, while dynamic languages implement polymorphism through composition. In one you have a strict hierarchy, while in the other you don’t. Its as simple as that. Besides Jeremy’s examples you should definitely look outside the .NET and Java world to see why this is so important.

@Jeremy Hurray! Glad to have you on the side of righteousness! I’ve been saying the same thing now for a while, although probably not as nicely as you just did.

One nit though. Language Oriented Programming, or using Domain Specific Languages (DSL), is alot more than building a library with a fluent interface. I don’t consider a library with just a fluent interface to be a DSL.

IronRuby is progressing nicely. The code drop from Mix looks to be pretty good, but it is not a complete Ruby implementation yet. The DLR hosting API should be much more stable moving forward as well. I believe the plan is for a 1.0 release later this year.

http://www.sergiopereira.com/articles/xmlbuilder.html Sergio Pereira

@Whatever
Mmm, I thought the name of this site was “Code Better”… Not “Code Again” …
You may be reading a blog that is not aligned with your priorities, that’s understandable, but a waste of your time when you should be getting the job done in the first place. Just a thought.

It’s hard for me to adopt fluent interfaces in my C# code after having tasted how they are created and used in Ruby. I’m taking a pass on fluent C# APIs for the time being.

http://neilmosafi.blogspot.com Neil Mosafi

Hmm agreed, but i still don’t think C# needs duck typing. it just doesn’t feel very C like and there are other languages out there which allow this.

Actually I’ve always wished that C# had a “typedef” operator, like in C++… it lets you alias any type with another name. A simple example could be something like this:

namespace MyNamespace {
typedef StringIntDictionary Dictionary;
}

Then you could then just use StringIntDictionary everywhere that the namespace gets imported. It would essentially allow you to alias all the generic arguments so you only have to define them in one place.

http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

@Whatever,

I’m trying to find better and better ways of doing things with less effort. “Just get ‘r done” often equates to “work hard, not smart.” According to the Standish Chaos report, something like 75%-80% of all software projects fail, so I don’t think we can say just “get ‘r done” is really working for us.

Dan

@Whatever (fitting name)

I’m sure it depends on what you mean by “just getting the job done”. I hope, I hope, I hope it’s not the ‘copy/paste’ mentality (as your comment implies) ’cause that’s definatley not what this blog or discussion is about.

Whatever

Have you tried just getting the job done, instead of constantly looking for the the coolest and latest toys? Just a thought….

False dichotomy there a little bit. You can have “duck” typing and compile time checking simultaneously, and some of the functional languages do this. It’s C#/Java style type systems that are giving me heartburn here.

Readability, Readability, and Readability. It makes a bigger difference when you try to make internal DSL’s and language oriented API’s.