Functional Languages Under .NET/CLR
Numen writes "With all the talk of .NET being thrown about there is a common factor occuring through many discussions, namely the claim that .NET will be unable to address functional and logic languages such as Prolog and LISP.
To this end I would like to drawn peoples' attention to two resources, that shown how this may well be a non-issue, and to ask, does this change anybodies mind?
"
After reading Miguel's long response to the Register article, I've really changed my mind about .NET architecture. I think I'm going to get a book and start learning it, maybe try to contribute to his effort.
Moderation: Put your hand inside the puppet head!
Another good example, as covered in Dr. Dobbs last issue, is Mondrian. You can read a paper about it here(it's a PDF). You can download the compiler and view documentation at the mondria-script web-site.
.NET Framework.
Here's a blurb from Dr. Dobbs:
Mondrian is a modern, purely functional language specifically designed to leverage the possibilities of the
/* CDM */
Does anyone know how .NET does for speed?
.NET introduce an even bigger overhead, or have they sorted it out?
.NET instead? Will the tailor-made version be more efficient because it's designed with the language in mind, or does the benefit of having all the optimisations done on a common system compensate for that?
ie, Java takes an absolute age to initialise which makes it unsuitable for desktop applications or utilities (although people still try... maybe in a few years' time...).
Does
Also, is there any overhead for languages that aleady use a VM (eg, python, perl) if they switch to
I really like the idea of a common cross-platform runtime, but not if it makes my text editor take 5 seconds to load!
.NET is just another one of Microsoft's over-engineered solutions. It looks simple on the outside, but when you get down to it the complexity is overwhelming. It's really sad to see so many open source developers being lulled by Microsoft's latest technological tactic.
.NET well!
Who out there remembers DDE, OLE, MAPI or DocObjects? How about MFC (.NET 0.5...)? If you do, remember how well (not very!) these "technologies" worked outside of the boxes Microsoft created them for? Has anyone out there actually tried to work with, for example, Exchange server?
Microsoft fears clonability, and to prevent it they create complex APIs with lots of hidden underspecifications. Then they get developers on board by creating pretty, easy-to-use tools and hosting big developer conferences. And they make it feel cool through shrewd marketing. But at the end of the day, you find that you've spent 90% of your time trying to work around some deficiency. And it's not because Microsoft was especially dumb when implementing this stuff, its just that the stuff is needlessly complex to begin with!
We're doing fine as we are. Don't drink from the
Why? One major advantage of functional programming languages for optimization is that the compiler knows that almost nothing can change behind its back: variables can't get updated, data structures can't get changed, etc. With VLIW architectures like Itanium and hyperthreading, functional programming languages can potentially do much better relative to traditional languages than on older processors. But in order to so so, their compilers need a degree of control over code generation that simply isn't available if you go through CLR or JVM.
Furthermore, the entire runtime of a functional language is optimized for the kinds of allocation patterns that come along with functional programming, while CLR and JVM are optimized for OOP. For lazy functional languages, there are some additional issues when it comes to expressing lazy evaluation efficiently.
Altogether, though, I think it really doesn't matter. CLR and JVM are good and fairly flexible platforms, but platform evolution won't stop here. If anything, Sun is a bit more honest in this regard, making no bones about the fact that JVM is primarily a Java platform, even though there are dozens of other language frontends available for it; CLR claims universality, but really isn't any better than JVM.
If you don't care that much about performance, you can use your functional language under CLR and JVM. If you want a high-performance functional programming language, you can use one of the dedicated native code compilers and runtimes that will continue to be available. CLR and JVM will not end the evolution of other runtimes.
The problem is not whether a compiler/interpreter for any language can use teh VM as the targeted back end. The problem is whether Microsoft's claim of language interoperability is true. So far the answer seems to be no. One can use all of their favourite languages features on a .NET compiler/interpreter but they cannot export any interfaces that may rely on some of those features: dynamic typing, closures, unsigned types etc. So what happens is Microsoft ends up effectively promoting a single programming style: essentialy C# except the syntax can be modified to look like your favourite language. No self respecting LISP, Scheme, ML, Haskell, Prolog etc. programmer is going to deliberately write inefficient code (and imperative style explicit looping is usually terribly inefficient in these languages as one example) simply because they are living withing the .NET CLR jail cell. Therefore they will use the language with the least impedance mismatch to the CLR: C#.
.NET CLR makes this seem like one tof the few wise choices they made so far.
As has been mentioned often, the Java JVM has many of the same issues. However the developers of the Java JVM never claimed to efficiently support languages other than Java as first class citizens. The recent furor over the
So to reiterate, the issue is not whether a language can be targeted to the virtual machine, it's whether the object code produced from source code in two different languages can interoperate and the answer is simply no, only the subset of features shared by C# and other languages can interoperate.
I took a look around and found this link to a guy called Don Syme at Microsoft Research who appears to be working on just this.
There's also the Mondrian project, which implements Haskell.
I'm actually excited about the .NET framework (well, the CLR) because it will mean I can use my favorite functional language, SML, to write Windows apps.
It's also from MSR: http://research.microsoft.com/Projects/SML.NET/
Why do we care? In a really old thread I rant about the virtues of modern functional languages (and indirectly, SML). I think it's still relevant, though most of the other languages associated with .NET (ie, C#) have some of the same basic benefits now (like safety and portability). Here:
http://slashdot.org/comments.pl?sid=6343&threshold =1&commentsort=0&mode=thread&cid=929697
If you want to learn SML, or learn why I think it is so cool, maybe you'd like my under-construction tutorial called SML for Hackers: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/tom 7misc/docs/sml/ml-for-hackers.txt?rev=1.3&content- type=text/vnd.viewcvs-markup
I think that this is an instance of an unclear question. The question is not "Is it possible to implement functional languages in .Net?", but rather, "Do the bytecode primitives efficiently support execution of functional language primitives?"
You might be able to implement a functional language interpreter supporting closures, lazy evaluation, etc., in the standard bytecode, but that's not the point. The point of the CLI is to effectively support efficient execution of programs written in ANY language. Therefore, writing another layer on top of the bytecode to support features unique to functional languages eliminates many advantages functional languages provide, and can potentially disallow correct execution of complex functional programs.
So, if the bytecode representation was designed to support object-oriented languages, it's probable that it WILL NOT efficiently support recursion and partial evaluation. This is the crux of the argument, and why people are concerned with the existing bytecode spec.
There is a lot of work being done in this area, though, so there is hope that this will be resolved. After all, Microsoft does have some of the best minds in functional programming thinking about the problem.
For more information, see:
http://research.microsoft.com/~dsyme
http://www.research.microsoft.com/~emeijer
http://www.mondrian-script.org
- j
Okay, I apoligize for an extra long post here, but I still see people mischaracterizing functional programming. So I'm going to take a few excerpts from "Why Functional Programming Matters" by John Hughes. It's a short paper, worth your time if you're new to the functional paradigm.
No Side Effects:
Functional programs contain no side-effects at all. A function call can have no effect other than to compute its result. This eliminates a major source of bugs, and also makes the order of execution irrelevant - since no side-effect can change the value of an expression, it can be evaluated at any time. This relieves the programmer of the burden of prescribing the flow of control. Since expressions can be evaluated at any time, one can freely replace variables by their values and vice versa - that is, programs are "referentially transparent". This freedom helps make functional programs more tractable mathematically than their conventional counterparts.
Higher Order Functions:
Functional languages allow functions which are indivisible in conventional programming languages to be expressed as a combi-nation of parts - a general higher order function and some particular specialising functions. Once defined, such higher order functions allow many operations to be programmed very easily. Whenever a new datatype is defined higher order functions should be written for processing it. This makes manipulating the datatype easy, and also localises knowledge about the details of its represen-tation. The best analogy with conventional programming is with extensible languages - it is as though the programming language can be extended with new control structures whenever desired.
Lazy Evaluation:
A complete functional program is just a function from its input to its output. If f and g are such programs, then (g . f ) is a program which, when applied to its input, computes g (f input). The program f computes its output which is used as the input to program g. This might be implemented conventionally by storing the output from f in a temporary file. The problem with this is that the temporary file might occupy so much memory that it is impractical to glue the programs together in this way. Functional languages provide a solution to this problem. The two programs f and g are run together in strict synchronisation. F is only started once g tries to read some input, and only runs for long enough to deliver the output g is trying to read. Then f is suspended and g is run until it tries to read another input. As an added bonus, if g terminates without reading all of f 's output then f is aborted. F can even be a non-terminating program, producing an infinite amount of output, since it will be terminated forcibly as soon as g is finished. This allows termination conditions to be separated from loop bodies - a powerful modularisation. Since this method of evaluation runs f as little as possible, it is called "lazy evaluation". It makes it practical to modularise a program as a generator which constructs a large number of possible answers, and a selector which chooses the appropriate one. While some other systems allow programs to be run together in this manner, only functional languages use lazy evaluation uniformly for every function call, allowing any part of a program to be modularised in this way. Lazy evaluation is perhaps the most powerful tool for modularisation in the functional programmer's repertoire.
Why you might care:
Modularity is the key to successful programming. Languages which aim to improve productivity must support modular programming well. But new scope rules and mechanisms for separate compilation are not enough - modularity means more than modules. Our ability to decompose a problem into parts depends directly on our ability to glue solutions together. To assist modular programming, a language must provide good glue. Functional programming languages provide two new kinds of glue - higher-order functions and lazy evaluation. Using these glues one can modularise programs in new and exciting ways... Smaller and more general modules can be re-used more widely, easing subsequent programming. This explains why functional programs are so much smaller and easier to write than conventional ones. It also provides a target for functional programmers to aim at. If any part of a program is messy or complicated, the programmer should attempt to modularise it and to generalise the parts. He should expect to use higher-order functions and lazy evaluation as his tools for doing this.