You are previewing Programming F#.

Programming F#

Cover of Programming F# by Chris Smith Published by O'Reilly Media, Inc.
O'Reilly logo

Visual Studio 2010

Tools are the lifeblood of any programming language, and F# is no different. While you can be successful writing F# code in your favorite text editor and invoking the compiler exclusively from the command line, you’ll likely be more productive using tools. Like C# and VB.NET, F# is a first-class citizen in Visual Studio. F# in Visual Studio has all the features you would expect, such as debugger support, IntelliSense, project templates, and so on.

To create your first F# project, open up the Visual Studio IDE and select File→New Project from the menu bar to open the New Project dialog, as shown in Figure 1-1. Select Visual F# in the left pane, select F# Application in the right pane, and click OK.

Select F# Application to start your first F# project

Figure 1-1. Select F# Application to start your first F# project

After you click OK in the New Project dialog, you’ll see an empty code editor, a blank canvas ready for you to create your F# masterpiece.

To start with, let’s revisit our Hello, World application. Type the following code into the F# editor:

printfn "Hello, World"

Now press Control + F5 to run your application. When your application starts, a console window will appear and display the entirely unsurprising result shown in Figure 1-2.

Hello, World in F#

Figure 1-2. Hello, World in F#

Your Second F# Program

It may be startling to see a program work without an explicit Main method. You will see why this is admissible in the next chapter, but for now let’s create a more meaningful Hello, World–type program to get a feel for basic F# syntax.

The code in Example 1-1 will create a program that accepts two command-line parameters and prints them to the console. In addition, it displays the current time.

Example 1-1. Mega Hello World

(*
Mega Hello World:
Take two command line parameters and then print
them along with the current time to the console.
*)

open System

[<EntryPoint>]
let main (args : string[]) =

    if args.Length <> 2 then
        failwith "Error: Expected arguments <greeting> and <thing>"

    let greeting, thing = args.[0], args.[1]
    let timeOfDay = DateTime.Now.ToString("hh:mm tt")

    printfn "%s, %s at %s" greeting thing timeOfDay

    // Program exit code
    0

Now that you have actual F# code, hopefully you are curious about what is going on. Let’s look at this program line by line to see how it works.

Values

Example 1-1 introduces three values named greeting, thing, and timeOfDay:

    let greeting, thing = args.[0], args.[1]
    let timeOfDay = DateTime.Now.ToString("hh:mm tt")

The key thing here is that the let keyword binds a name to a value. It is worth pointing out that unlike most other programming languages, in F# values are immutable by default, meaning they cannot be changed once initialized. We will cover why values are immutable in Chapter 3, but for now it is sufficient to say it has to do with functional programming.

F# is also case-sensitive, so any two values with names that only differ by case are considered different:

let number = 1
let Number = 2
let NUMBER = 3

A value’s name can be any combination of letters, numbers, an underscore _, or an apostrophe '. However, the name must begin with a letter or an underscore.

Note

You can enclose the value’s name with a pair of tickmarks, in which case the name can contain any character except for tabs and newlines. This allows you to refer to values and functions exposed from other .NET languages that may conflict with F# keywords:

let ``this.Isn't %A% good value Name$!@#`` = 5

Whitespace Matters

Other languages, like C#, use semicolons and curly braces to indicate when statements and blocks of code are complete. However, programmers typically indent their code to make it more readable anyway, so these extra symbols often just add syntactic clutter to the code.

In F#, whitespace—spaces and newlines—is significant. The F# compiler allows you to use whitespace to delimit code blocks. For example, anything indented more than the if keyword is considered to be in the body of the if statement. Because tab characters can indicate an unknown number of space characters, they are prohibited in F# code.

Note

You can configure the Visual Studio editor to automatically convert tab characters into spaces by changing the relevant setting under Tools→Options→Text Editor→F#.

Reviewing Example 1-1, notice that the body of the main method was indented by four spaces, and the body of the if statement was indented by another four spaces:

let main (args : string[]) =

    if args.Length <> 2 then
        failwith "Error: Expected arguments <greeting> and <thing>"

    let greeting, thing = args.[0], args.[1]
    let timeOfDay = DateTime.Now.ToString("hh:mm tt")

    printfn "%s, %s at %s" greeting thing timeOfDay

    // Program exit code
    0

If the body of the if statement, the failwith, was dedented four spaces and therefore lined up with the if keyword, the F# compiler would yield a warning. This is because the compiler wouldn’t be able to determine if the failwith was meant for the body of the if statement:

[<EntryPoint>]
let main (args : string[]) =

    if args.Length <> 2 then
    failwith "Error: Expected arguments <greeting> and <thing>"

Warning FS0058: possible incorrect indentation: this token is offside of
context started at position (25:5). Try indenting this token further or
using standard formatting conventions

The general rule is that anything belonging to a method or statement must be indented further than the keyword that began the method or statement. So in Example 1-1, everything in the main method was indented past the first let and everything in the if statement was indented past the if keyword. As you see and write more F# code, you will quickly find that omitting semicolons and curly braces makes the code easier to write and also much easier to read.

.NET Interop

Example 1-1 also demonstrated how F# can interoperate with existing .NET libraries:

open System

// ...

let timeOfDay = DateTime.Now.ToString("hh:mm tt")

The .NET Framework contains a broad array of libraries for everything from graphics to databases to web services. F# can take advantage of any .NET library natively by calling directly into it. In Example 1-1, the DateTime.Now property was used in the System namespace in the mscorlib.dll assembly. Conversely, any code written in F# can be consumed by other .NET languages.

For more information on .NET libraries, you can skip ahead to Appendix A for a quick tour of what’s available.

Comments

Like any language, F# allows you to comment your code. To declare a single-line comment, use two slashes, //; everything after them until the end of the line will be ignored by the compiler:

    // Program exit code

For larger comments that span multiple lines, you can use multiline comments, which indicate to the compiler to ignore everything between the (* and *) characters:

(*
Mega Hello World:
Take two command line parameters and then print
them along with the current time to the console.
*)

For F# applications written in Visual Studio, there is a third type of comment: an XML documentation comment. If a comment starting with three slashes, ///, is placed above an identifier, Visual Studio will display the comment’s text when you hover over it.

Figure 1-3 shows applying an XML documentation comment and its associated tooltip.

XML documentation comments

Figure 1-3. XML documentation comments

The best content for your career. Discover unlimited learning on demand for around $1/day.