I got my hardcopy of SDTimes a few days ago, but have been waiting for it to go online before writing about the special report on the CLR. The article is written by Larry O'Brien, and I think he's a bit too breathless in his praise for it. Some of the inconsistency starts early. He makes a point about how most developers prefer type systems like what C, C++, and Java have - which, based on practice in the industry, is certainly true:
Certainly, the programming community has voted repeatedly to embrace languages that derive from C. This preference is a combination of an appealing syntax (explicit typing is appealing for programming in the large), professionalism by association (real programmers use curly braces) and performance (all popular C-derived languages have rejected “everything is an object” for at least some primitive types).
While I'd call those flaws, most people in the industry don't agree with me. So why do I say that the inconsistency starts early? Well, Larry is writing about LINQ (Language INtegrated Query) like it's the second coming for software developers. Here, let me quote him:
To understand the power of LINQ and how it seems foreshadowed in the evolution of C#, forgive a quick foray into code. Consider Listing 1 (page 29), which gives a hint of a LINQ-like function called “FindAll.” After the initial “using” statements (which make available important classes), we define a new type of function called a Predicate. Predicates are functions that take a value and do some calculation that results in a Boolean evaluation. In C#, function signatures such as this are first-class language features called “delegates.” These have been a feature of C# since the beginning. Our Predicate function, though, works on any type; we don’t need a separate definition for functions that evaluate integers, or strings or customer records. This “generic” functionality was added to C# in the 2.0 version.
If you take a look at FindAll, you see that, for convenience, it’s “static” (using it does not require an instance of type “Program” to have been instantiated) and publicly visible. Ignoring the parameterized type “T”s that sprinkle its signature, it should be clear that FindAll outputs a List after taking as input a List and a Predicate. The passed-in Predicate evaluates each of the values in the passed-in list to build the returned list (the predicate is applied with the call to function(value)). Note how generic it is: It makes no assumptions on the type of values it operates on and no assumptions on the workings of the supplied Predicate.
After telling us how valuable explicit typing is, the first thing you notice is that the example is using generics to avoid explicit typing. Kind of makes you wonder how valuable it is, if the real power is available only if you chuck the concept. Here's the code listing he refers to, and that's where I really wanted to make a point:
delegate bool Predicate<T>(T value);
static public List<T>FindAll<T>(List<T> inList, Predicate<T>predicate)
List<T> retval = new List<T>();
foreach (T value in inList)
static void Main(string args)
List<int> intList = new List<int>();
for (int i = 0; i < 10; i++)
for (int modulus = 2; modulus < 5; modulus++)
// Notice how a new function is defined here
List<int>evenList = FindAll<int>(intList, delegate(int i)
return i % modulus == 0;
Console.Write("The even multiples of "
+ modulus + " in range[1..10] are = ");
foreach (int i in evenList)
Console.write(i + " ");
What that does is take a list of numbers from 1 to 10, then iterate over them, pulling out first the numbers that are 0 modulo 2, 3, and 4. The above is supposed to be a model of simplicity, showing the power of LINQ in the CLR. Here's Larry again:
By combining delegates, generics and the closurelike "anonymous delegates with outer variable capture" you can create very concise expressions for working with collections. Of course, there is much more to LINQ. A complete SQL-like query ability is much more complex than what is shown here. The structural issues of selection and extension go beyond C# 2.0’s capabilities. And ultimately there’s a qualitative difference between a querying API and query built into the syntax of the language. Nevertheless, there’s a distinct feeling of design decisions made years ago contributing to a capability only now being previewed.
Well. The problem is, this - they had to build it into the CLR with a bunch of syntax. The equivalent Smalltalk?
| list |
list := #(1 2 3 4 5 6 7 8 9 10).
2 to: 4 do: [:index | | answers |
answers := list select: [:each | (each \\ index) = 0].
Transcript show: 'values equal to 0 modulo ',
index printString, ' ',
Gee, that's simpler, isn't it? And unlike the CLR, Smalltalk didn't need to bake that query into the syntax - it's just a library message that any collection understands. Meaning, it's generic without all that extraneous syntax. Microsoft, like Sun, is grasping weakly at the power that Smalltalk already has via added complexity. Apparently, the "value" of explicit typing is such that you need to saddle developers with a pile of syntax in order to deliver "power".
I don't really need to go to the trouble of defining the generic function up front, because #select: is already in the library. But wait - there's more! Say I wanted to add a new query "function" to all collections? Easy - I find class Collection in the system, and I add the method. Bam - there it is. I can make sure to version it off in my own package so that only people who need it will have it loaded as well.
The thing I find interesting is the Java/CLR approach to power - it always involves adding a pile of new syntax to the language - which is why the books defining those systems keep getting thicker. You need a scorecard just to keep up with the syntax.
At the end of an associated column on Iron Python, column, Larry brings up something I addressed the other day:
#Smalltalk (pronounced Sharp Smalltalk, and available from www.refactory.com) seems to be close to a full implementation of the Smalltalk language but does not have the workspace/browser environment that many consider the heart of Smalltalk’s power. Similarly, while there are a few Lisp-like languages for .NET, there’s not a CLOS environment for the CLI. Whether this is because the CLI erects technical roadblocks of progress or because there’s insufficient motivation for commercial or open-source development of such environments, it’s regrettable and only serves to further the dominance of C# on the platform.
As I stated the other day, we actually looked at the CLR as a host for Smalltalk. It simply wasn't suitable, given the level of investment we would have had to make.