Home

Introduction

 

Fundamentals

 

Introduction

 

 

     
 
 

 

   
   
 

Previous Copyright © 2015 FunctionX Next

Home

F# Topics: Namespaces

 

Fundamentals of Namespaces

 

Introduction

A namespace is a technique of creating a section of code to isolate names that can be uniquely identified even if some of those names are used somewhere else in a program.

Creating a Namespace

The primary formula to create a namespace is:

namespace namespace-name
    body

Start with the namespace keyword. In a document that contains the creation of a namespace, that creation must be the first line of code. As a result, the following code will fail:

let message = "Welcome to the wonderful world of F#!"

namespace . . .

The Name of a Namespace

The name of a namespace follows the rules of names in the F# language. The name should start with a letter in uppercase. Here is an example:

namespace Bookeeping
    ...

We will come back to issues about the name of a namespace. On the next line, create a body for the namespace.

The Contents of a Namespace

The line under namespace and its name is the body of the namespace. The body of a namespace can contain classes and other types. It cannot contain variable declaration or a direct call to a function. As a result, the following program will produce an error:

open System
open System.Windows.Forms

namespace Programming
type Creator(title) =
    member this.Create() =
        let exercise = new Form()
        exercise.Text <- title

        Application.Run exercise

let app = new Creator("Application Development")

app.Create()

A namespace is a good place to create and organize classes. The body of a namespace doesn't have to be indented. Here is an example of a namespace that contains a class:

namespace Geometry

type Pentagon(side : float) =
    let s = ref side

    member this.Side with get() = !s and set(value) = s := value

Accessing a Member of a Namespace

 

Introduction

To access a member of a namespace outside that namespace, you must fully qualify its name. You have two primary options:

Using Multiple Files in a Project

When you create a project in Microsoft Visual Studio, it creates a default file named Program.cs (remember that you can keep that name or you can rename it if you want). You can see the list of your files in the Solution Explorer:

Using Multiple Files in a Project

A file that contains F# code is also called a code file (in Visual C# and Visual Basic) or a source file (in Visual F#). You can use just that source file and you can create as many functions and/or types (classes, etc) in it. As an alternative, you can add one or more source files to your project to better organize your functions and types.

To add a new file to your project, in the Solution Explorer of Microsoft Visual Studio, right-click the name of the project -> Add -> New Item... In the Add New Item dialog box, click Source File and give a name to the file:

Using Multiple Files in a Project

When you are ready, click Add. In the same way, you can add as many source files as you want. The document of every file should start with a namespace except for the last file, which is usually the file that contains the call to the Application.Run() method for a graphical application or the file that contains the entry point.

After starting a project in Microsoft Visual Studio, the default file (Program.cs) is considered the first, last, and only file. If you add a new file, it becomes the last. When you compile your project, the compiler refers to the list of files in the Solution Explorer. Under the References node, they would be something like Programs.fs, app.config, File1.fs, File2.fs, File3.fs, etc. When compiling, the compiler proceeds from top-bottom. If the content of the top file is not included in a namespace and the content of the bottom file is included in a namespace, the compiler would produce an error. You have various options:

Here is an example of a first file named Pentagon.fs with a namespace:

namespace Geometry

type Pentagon(side : float) =
    let s = ref side

    member this.Side with get() = !s and set(value) = s := value
    member this.Perimeter with get() = !s * 5.00
    member this.Diagonal with get() = (1.00 + (sqrt 5.00)) * 0.50 * !s
    member this.Area with get() = sqrt(5.00 * (5.00 + (2.00 * (sqrt 5.00)))) * 0.25 * !s * !s

Here is an example of a last file named Program.fs in the same project:

open System
open System.Windows.Forms

let exercise = new Form(Width = 220, Height = 240, Text = "Polygon: Pentagon")

// Label: Side
exercise.Controls.Add(new Label(Left = 23, Top = 21, Width = 31, Text = "Side:"))

// Text Box: Side
let txtSide = new TextBox(Left = 83, Top = 18, Width = 100, Text = "0.00")
exercise.Controls.Add txtSide

// Button: Calculate
let btnCalculate = new Button(Left = 83, Top = 49, Width = 100, Text = "Calculate")
exercise.Controls.Add btnCalculate

// Label: Perimeter
exercise.Controls.Add(new Label(Left = 23, Top = 86, Width = 54, Text = "Perimeter:"))

// Text Box: Perimeter
let txtPerimeter = new TextBox(Left = 83, Top = 83, Width = 100)
exercise.Controls.Add txtPerimeter

// Label: Diagonal
exercise.Controls.Add(new Label(Left = 23, Top = 112, Width = 52, Text = "Diagonal:"))

// Text Box: Diagonal
let txtDiagonal = new TextBox(Left = 83, Top = 109, Width = 100)
exercise.Controls.Add txtDiagonal

// Label: Area
exercise.Controls.Add(new Label(Left = 23, Top = 138, Width = 32, Text = "Area:"))

// Text Box: Area
let txtArea = new TextBox(Left = 83, Top = 135, Width = 100)
exercise.Controls.Add txtArea

let btnCalculateClick e =
    let side = float txtSide.Text

    let pent = new Geometry.Pentagon(side)

    let strPerimeter = sprintf "%f" pent.Perimeter
    let strDiagonal  = sprintf "%f" pent.Diagonal
    let strArea      = sprintf "%f" pent.Area 

    txtPerimeter.Text <- strPerimeter
    txtDiagonal.Text <- strDiagonal
    txtArea.Text <- strArea
btnCalculate.Click.Add btnCalculateClick

let btnClose = new Button(Left = 83, Top = 168, Width = 100, Text = "Close")
let btnCloseClick e = exercise.Close()
btnClose.Click.Add btnCloseClick
exercise.Controls.Add btnClose

Application.Run exercise

Here are examples of running the program:

Using Multiple Files in a Project Using Multiple Files in a Project

Creating Many Namespaces

In a document, you can create as many namespaces as you want. Here is an example of a document with two namespaces:

namespace CommercialBank
type Employee =
    class
    end

namespace VehicleDealership
type Employee =
    class
    end

type Customer =
    class
    end

type Vehicle =
    class
    end

Nesting in a Namespace

One namespace can be nested in another namespace. Because all namespaces are created from the left side of the document, to indicate that a namespace is nested, you must qualify its name by indicating what its parent namespace(s) is (are). Here are examples:

namespace Mathematics
namespace Mathematics.Algebra // The Algebra namespace is nested in the Mathematics namespace
namespace Mathematics.Algebra.Elementary // The Elementary namespace is nested in the Algebra namespace that itself is nested in the Mathematics namespace
namespace Mathematics.Algebra.Equations // The Equations namespace is nested in the Algebra namespace that itself is nested in the Mathematics namespace 
namespace Mathematics.Arithmetic // The Arithmetic namespace is nested in the Mathematics namespace
    

You can then add the members anyway you want. To start, remember that a namespace cannot contain declared variables and functions but it can contain enumerations and classes. Here are examples:

namespace Mathematics
type Topics =       // The Topics enumeration is defined, or is a member of, the Mathematics namespace
    | Quantity
    | Structure
    | Space
    | Other
namespace Mathematics.Algebra // The Algebra namespace is nested in the Mathematics namespace
namespace Mathematics.Algebra.Elementary // The Elementary namespace is nested in the Algebra namespace that itself is nested in the Mathematics namespace
type Operator(o) = // The Operator class is a member of the Mathematics.Algebra.Elementary namespace
    class
    end
namespace Mathematics.Algebra.Equations // The Equations namespace is nested in the Algebra namespace that itself is nested in the Mathematics namespace
type Quadratic(a, b, c) = // The Quadratic class is defined, or is a member of, the Mathematics.Algebra.Equations namespace
    class
    end
namespace Mathematics.Arithmetic // The Arithmetic namespace is nested in the Mathematics namespace
type Number() = // The Number class is defined the Mathematics.Arithmetic namespace
    class
    end
type Addition(a, b) = // The Addition class is defined the Mathematics.Arithmetic namespace
    class
    end

Referring to Members of a Namespace

Outside a namespace, before referring to the members of a namespace, somewhere in the top section of the file, type open followed by the namespace or the whole name where the member was created. Here are examples:

open Mathematics
open Mathematics.Algebra
open Mathematics.Algebra.Elementary
open Mathematics.Algebra.Equations
open Mathematics.Arithmetic

As an alternative, or in combination, to refer to (one of) its member(s), you can fully qualify the name of a  member from its parent(s). From the above example, to access the Quadratic class, you start from the most top namespace followed by each child namespace until the class's name. This would be:

Mathematics.Algebra.Equations.Quadratic

The Name of a Namespace . . .  Again

As seen so far, when accessing a namespace, you use its whole ancestry. In fact, when creating a namespace, you can specify a lineage that you anticipate would be essential. Here is an example:

namespace Chemistry.Compounds.Reactions
    type Atom(a) =
        class
        end

After creating a namespace like this, you can access its members using the whole qualified name. Here is an example:

namespace Chemistry.Compounds.Reactions
    type Atom(a) =
        class
        end

namespace Studies
type Research() =
    let t = Chemistry.Compounds.Reactions.Atom("O")

Based on this, you can specify a name of a namespace that includes various parts even if those parts don't exist. To resume, the name of a namespace can be in one word or it can include various parts separated by periods.

If you had created a name of a namespace and made it in different parts, if you want, somewhere else in the file, you can create namespaces that include some parts that were used in the original name. Here is an example:

namespace Chemistry.Compounds.Reactions
    type Atom(a) =
        class
        end

namespace Chemistry.Compounds
    type Substance(element1, element2) =
        class
        end

namespace Studies
type Research() =
    let t = Chemistry.Compounds.Reactions.Atom("O")
    let c = Chemistry.Compounds.Substance("hydrogen", "helium")

Home Copyright © 2014-2015 FunctionX Home