The Least a C# Programmer Needs to Know about F# Part II--Modules
Jomo Fisher--Many languages, especially those in the OO vein, require an outermost class to put code in. Usually, good practice requires an enclosing namespace as well. F# allows functions and even function calls in the outermost scope. Here is the minimal F# program:
printf "Hello!"
Really, that's the whole thing. My first concern upon seeing this was that the all these functions in the global namespace would eventually collide in larger projects making things unmanageable. It seemed a lot like returning to the nasty global state that you sometimes see in older C codebases. It turns out, however, that F# puts each file's functions, function calls and types inside its own construct called a "Module". Consider this slightly modified version:
// File Hello.fs
#light
let Say s = printf s
Say "Hello!"
Which is saved in file called Hello.fs. This defines a function called 'Say' and then calls it. Using Reflector, I can see the Say method decompiled into C#:
[CompilationMapping(SourceLevelConstruct.Module)]
public class Hello
{
public static T Say<T>(Format<T, TextWriter, Unit, Unit> s) {
return Pervasives.printf<T>(s);
}
}
The F# compiler has put the method into a public class called Hello . This is F#'s representation of the Module. The class name Hello is derived from the file name Hello.fs. You can change the Module name if you like:
module MyModule =
let Say s = printf s
Say "Hello!"
For larger projects, I think its best to explicitly name modules. For smaller, one-off projects its convenient not to have to think about it.
In most .NET projects I've worked on, there usually ends up being a few utility classes that just have a bunch of related static methods in them. These are functions that just didn't cleanly fit the OO paradigm. Its tempting to think of these classes as code smells. After all, surely there's a clean OO representation for them that I haven't thought of yet, right?
I think the answer to this is: no, not everything fits well into object-orientation.
My proof by existence is to consider .NET's Stream classes that were released in .NET 1.0. These classes were extremely well factored. They beautifully hid the underlying media or communication protocol behind an abstract stream of information. They were also damn hard to use for simple cases. In a later .NET release the File, Path and Directory classes were introduced. These were just classes with nice, simple static methods for doing the common things you want to do with files, paths and directories.
F# makes this style of API a first-class citizen: the Module.
So am I saying good-bye to OO? No way. But I consider it a hammer and not every problem is a nail.
This posting is provided "AS IS" with no warranties, and confers no rights.