Inside Microsoft's New F# Language
Robyn PetersonThe Grape Vine Rumors of a new .NET language have been circulating around the cyber-grapevine for the last year or so (see Slashdot, F# - A New .Net language), but have picked up speed as of late. The fire was fed by Mary Jo Foley's (columnist, Microsoft Watch) recent news story Add F# To the Alphabet Soup. Strangely enough, there hasn't been a peep from Microsoft. The only published information I can find is hosted on the Microsoft Research (MR) site. So, I donned my thinking cap, and proceeded with reckless abandon. Here begins the tale…
I began scouring Research.Microsoft.com looking for information, and what I found was fairly interesting. In a nutshell, what follows on the next few pages is a quick intro to F#: What is F#? What is the origin of F#? What the purpose of F# and what would it do for me? Should I use ML, F#, or Neither?
Note that this article is not a primer on how to program F#; it's merely a quick intro to let you know it's out there. I'm learning about this right now, as most of you probably are. I'm not so sure what to make of it, and I'm sure you have questions too. So after reading through this, let's bring the discussion into our forum, and debate whether Microsoft is making a smart move here, and whether you would you consider using F# for your .NET implementation.
Read on to learn more about F sharp...
Some cynics say that there are no more completely "new" ideas. Well, in this instance they're right. F# is derived from a series of different imperative and functional languages as are most modern languages (including Java and C).
For background, an imperative language – like COBOL, FORTRAN or Pascal -- is one that allows the use of variables which can be assigned values which are then updated later in the program. These variables can hold intermediate values or other values at the developer's discretion. For example, in an imperative language, a developer might first define a numeric variable "X", and assign it an initial value of 3 (X=3). Then during the course of the program, X might be changed through addition, subtraction or other numerical operations.
A lot of developers use variables for side-effects. A side effect occurs when the value of a variable is affected by a function and this modification of the variable is not necessarily the direct effect of that function. For example, if I write a function writeText() which writes text to a file (its main function) but for every character of text it writes, it increments a variable called (charsWritten). The modification of charsWritten is then a side effect of the function writeText(). A functional language is made up purely of functions, or expressions, such that names are assigned to values as if they were constant. So, variables are not updated as the program flow proceeds. Here is an example of how you assign a value to X in the functional language Scheme: (define X 3)
So, now the value of X is 3. If I type in the following code: (+ 2 X)
(Note that Scheme uses pre-fix notation. (+ 2 X) means the same thing as (X + 2). The value of 5 would be returned.
In reality, a purely functional language is difficult to find. It's also the subject of great debate. In the example above, I used Scheme, which is fairly close to being purely functional. For more information on Scheme, check out this Scheme manual.
With functional languages, the code itself is designed to evaluate mathematical expressions, not execute commands.
A Java or C program affects the state of a machine running the program, or communicating with it.
With a functional language, the only result is the value(s) that are computed by the program. A functional language is meant to be more mathematical at heart, and thus creates more separation between the lower level machine details and the developer's code. In a nutshell, functional programming is supposed to be a "higher level" of programming than Java or C.
This can be hard to grasp. My first language was C, and I found it difficult initially to adapt to the seemingly mystical functional programming paradigm. So, don't be put off if you don't quite understand functional programming from my short explanation. If you want to learn more about functional languages, I recommend taking a stab at Scheme (a dialect of Lisp).
The program flow of F# more closely resembles a functional language as the code consists mainly of functions (i.e. expressions). The key to F# is to rarely rely on the updating of variables for the purposes of creating side-effects (as is common in Java and C).
But from its imperative ancestors, F# does retain the ability to create variables and update these variables later. That implies that you can program in F# using a Java/C-mentality and use variables to keep track of various environmental factors.
Thanks to the wonderful world of the web, we're able to trace the genealogy of F# back a few generations. Here's what we found: At the heart of F# lies Objective Caml, or OCaml, and the .NET language C#. C#, as you probably already know, is based upon C/C++ and Java. OCaml is the latest incarnation of the Caml language. Caml is a dialect of ML.
Did I lose you? Well, I almost lost me. So, let's leave it at this: F# is, in essence, another dialect, or "manifestation" as Microsoft calls it, of a functional ML-like language mixed with the power of C#.
What is ML? ML is a functional language (similar to Scheme, as we discussed above) created about 20 years ago, primarily for research. ML is short for "meta-language", and as the name implies ML is primarily used to manipulate other languages. So a compiler, for example, is a great application to write using ML.
Don't expect to find any job postings for ML programmers, because it's not a widely used professional language. However, it's a fascinating language to learn--and if you've never worked with a functional language I highly recommend spending some time with either ML or Scheme.
ML creates an entirely different development environment, including interactive compilers that respond as you code. A very different mode of thinking is required to code in a functional language. Now, it's not LSD for developers, but in my opinion it's fairly mind-blowing.
Now, I won't lie--as far as functional languages go, I'm more familiar with Lisp (and Scheme specifically) and my experience with ML lies mostly in classrooms. So, chime in at the forum if you have some thoughts on ML.
The F# site boldly states that "F# is meant to bridge the best of the functional, imperative, object-oriented and typed-classed languages." That sounds great, but .NET already supports a myriad of languages, does it need another one?
For every language – so the thinking goes -- there should exist a subset of problems that it specifically, and optimally addresses. According to Microsoft, a subset of problems exist that aren't optimally solved by an existing language--and that subset is made up of simple, yet subtle problems.
Java and C# are inherently complex. Each contains a pantheon of objects and libraries that can be used by the developer to accomplish many tasks. Anyone who has programmed in Java or C# knows that the same goal can usually be accomplished many different ways, depending on the developer. Often a complex language spawns complex solutions --and complex code can be difficult to debug, update, and pass on to new developers. Here's where F# comes to the rescue: a simple subtle language designed to solve simple, subtle problems.
The classic illustration of this idea is the case of the Map function. Map is a function which applies other functions to data (you can think of Map as an assembly line, applying one function to every unit that passes by on the conveyor belt). In a nutshell, Map takes in a function and "maps" it onto some data. Put as simply as possible (but it's not simple), the map function takes in multiple parameters: a function, and data to apply that function to. In other words, Map is a function that takes a function as input and applies it to the data that's also sent to Map. Since Map is a function that applies another function to a set of data, it can be called a Higher Order function.
For instance, consider the Function square(int) which produces the square of any integer I give it. If I wanted to square every member of an integer array, then I could accomplish it in a Java-like language as follows: for (int i=0; i<myIntegerArray.length; i++) { myIntegerArray[i]=Square(myIntegerArray[i]); } Result: Every integer in my array would be squared.
It's not too complicated to write this code, but consider the case where I need to apply a range of functions to either a single element or to an array of elements,
I have two primary choices for implementation: Write the functions to handle one element, and then litter my program with for-loops every time I run across an array (as above). Write an overloaded version of the function that handles an array as input. Then each function would have two versions: one version that takes a single element as input, and another takes an array as input.
Both of these are somewhat reasonable solutions considering the language used.
However, let's thicken the plot--consider a pool of 50 or 100 functions that are defined to operate on a single-element. Then the program specifications change and you need to process arrays instead. To handle this challenge, you'd either have to write a for-loop every time you come across an array (yuck!) or you'd have to write an overloaded version of each function to handle the array as input (double yuck!).
With F#, as in ML, the more generic Map function would allow me to apply any function (like Square) to any element of an array. Plus, it can be developed very easily. It would look something like this: fun Map f [] = [] | Map f (h::t) = f h :: Map f t;
Where "fun" tells the compiler that this is a function definition, and 'f' is the function we're passing in. Map then applies whatever function we pass in to every member in the array (called a list in functional programming). Plus, I can send it any function. So it would work for Square, as in our example above, or it would with Cube() or any other function I send it.
Don't worry if you can't make complete heads or tails (a little ML-humor) of the Map example--let it suffice to say that in this type of problem, a functional language can deliver a solution in two lines of code whereas a language like Java or C would have many times more lines (and complexity). The developer is then better able to separate himself from some of the lower-level details of implementation (such as writing numerous for-loops, or overloading every function just to work on an array or a single integer).
To program the Map function in Java or C is no easy feat as we have to deal with some daunting complexity, including pointers to functions and generics. Now, it can be done (and probably some of you reading this article can do it quite quickly) but the point is, there are lots of programmers out there who would benefit from a simpler implementation.
Why not just use ML? With F#, Microsoft has sweetened the pot. Via simple method calls in the code, a developer is able to access .NET libraries by using a "." syntax. Here's a short example from a presentation put together at Microsoft Research: let findDLLs dir = (* call a static member in the System.IO.Directory class *) if (Directory.Exists dir) then let files = Directory.GetFiles(dir, "*.dll") in Arr.to_list files
This function, without getting into the precise syntax makes two calls to .NET functions, Directory.Exists and Directory.GetFiles. The function will return a list of the files that end with the "dll" extension.
In essence, we can say that F# plays "nicely" with .NET. The interplay between the two is useful (and necessary). It even seems fairly easy to use.
Final Thoughts With the simplicity of ML, and the power of .NET, Microsoft could have a winning language for .NET developers. However, we haven't given you the full story--mostly because the full story can't be written just yet. Only the preview version of the compiler is out, and so far the word hasn't spread too fast.
At the time this article was written, MS has yet to post a full tutorial on F#. Code samples had to be developed or plucked from research presentations (for a good source of F# info, check out this powerpoint presentation). A full review of F# is simply a bit premature right now. However, a discussion of F# is very relevant.
So, all of you developers out there, let us know what you think. Will F# be useful when developing .NET? Will you give it a test drive? What will the future of F# be?
Requirements to Use F# There are minimal requirements for running the F# compiler. The two lists below are directly pulled from the README file:
In order to compile F# on your computer, you'll need to have one of the following installed: VisualStudio.NET (MSDN) The Microsoft .NET Framework SDK (MSDN/Net) An installation of the Microsoft .NET Framework SDK Redistributable (MSDN/Net), though I have not tested this. The "redist" is a trimmed-down set of binaries containing just what is needed to run programs, but also contains the IL assembler needed by the F# compiler.
The runtime requirements for F# are as follows: You will need to have one of the above installed on your system in order to run F# programs. You will also need to have the F# libraries installed in the Global Assembly Cache or copied to your application directory. This is done when you install the F# compiler on your computer.
Links to Get It Yourself You can get more information (but not much more just yet) by checking out the F# site hosted off Microsoft Research.
The best way to learn F# is to get your hands dirty. You can download the preview version of the F# compiler from Microsoft Research (currently at version 0.612).
Copyright © 2004 Ziff Davis Media Inc. All Rights Reserved. Originally appearing in ExtremeTech.