Wrox Home  
Search
Professional .NET Framework 2.0
by Joe Duffy
April 2006, Paperback


The Language Spectrum

The CLR supports the entire spectrum of languages, from static to dynamic and everywhere in between. The Framework itself in fact provides an entire library for doing late-bound, dynamic programming, called reflection. Reflection exposes the entire CTS through a set of APIs in the System.Reflection namespace, offering functionality that facilitates compiler authors in implementing dynamic languages, and enables everyday developers to exploit some of the power of dynamic programming.

Let's take a brief look at some example languages from this spectrum. You'll find below four small programs, each printing out the 10th element in the Fibonacci series (a well-known algorithm, the naíve implementation of which is shown). Two of these examples are written in statically typed languages (C# and F#), one in a language in between (VB), and one in a dynamically typed language (Python). The primary differences you will notice immediately are stylistic. But one deeply ingrained difference is whether the IL they emit is typed or instead relies on dynamic type checking and binding.

C#

using System;

class Program
{
    static int Fibonacci(int x)
    {
        if (x <= 1)
            return 1;
        return Fibonacci(x - 1) + Fibonacci(x - 2);
    }

    static void Main()
    {
        Console.WriteLine(Fibonacci(10));
    }
}

F#

let rec fibonacci x =
    match x with
        0 -> 1
      | 1 -> 1
      | n -> fibonacci(x - 1) + fibonacci(x - 2);;

fibonacci 10;;

VB

Option Explicit Off

Class Program
    Shared Function Fibonacci(x)
        If (x <= 1)
            Return 1
        End If

        Return Fibonacci(x - 1) + Fibonacci(x - 2)
    End Function

    Shared Sub Main()
        Console.WriteLine(Fibonacci(10))
    End Sub
End Class

Python

def fib(i):
    if i <= 1:
        return 1
    return fib(i-1) + fib(i-2)

print fib(10)

You'll notice the C# version is the only one that mentions we're working with 32-bit int values. These are static type annotations and are needed for the compiler to prove type soundness at compile time. Many static languages like F#, on the other hand, use a technique called type inferencing, avoiding the need for annotations where they can be inferred by the use of literals. F# actually emits IL similar to C#'s, working with statically typed ints, although we never specified it in the source code. In other words, it infers the type of a variable by examining its usage. Languages that infer types ordinarily require type annotations where a type can't be inferred solely by its usage.

The other languages shown, VB and Python, emit code that works with Object — the root of the CTS type hierarchy — and choose to bind strongly at runtime. They do so by emitting calls into their own runtime libraries, which are based on reflection. Clearly, the performance of statically typed programs will often win out over dynamic, simply because they can emit raw IL instructions instead of relying on additional function calls to, for example, late-binding libraries. Some degree of clever runtime caching can significantly narrow this difference.

Wrapping Up

As we've seen, the CLR is a great platform for language diversity. No single language is perfect for all jobs, and many programmers actually bounce between languages, tailoring the choice to the specific project they are working on.

C#, VB, and C++ all ship as part of the .NET Framework 2.0 and Visual Studio 2005 release. F# can be downloaded from Microsoft Research at http://research.microsoft.com/downloads. And a shared source implementation of Python on the CLR can be downloaded at http://workspaces.gotdotnet.com/ironpython.

This article is adapted from Professional .NET Framework 2.0 by Joe Duffy (Wrox, 2006, ISBN: 0-7645-7135-4), from chapter 2 "Common Type System." Joe is a Program Manager on the CLR Team at Microsoft, where he works on WinFX and the .NET Framework.

Page 1 | Page 2 | Page 3