Enumerations Fundamentals

Introduction

Imagine you have a few constant natural numbers (it doesn't matter what those numbers are, as long as you know them) and you want to use them in a scenario such as a conditional statement. Here is an example:

```let membershipCategory = 20;

if membershipCategory = 10 then
printfn "Membership Category: Teen";
elif membershipCategory = 20 then
elif membershipCategory = 30 then
printfn "Membership Category: Senior";```

In this case, we used the constants 10, 20, and 30 to perform comparisons. Those numbers may mean different things to different people. Instead of using such numbers, you can name them and use those names in your code. An enumeration is a technique of creating names to be used in place of constant numbers.

Creating an Enumeration

The primary formula to create an enumeration is:

```type EnumerationName =
| MemberName1
| MemberName2
| MemberName_n```

You start with the required type keyword and an empty space. This is followed by a name for the enumeration. The name follows the rules we saw for names of classes. The name is followed by the = sign followed by the body of the enumeration. Each member of the enumeration starts on its own line with | (a beam) and a name. Here is an example:

```type Category =
| Teen
| Senior```

Using an Enumeration

As always in F#, you can declare a variable without specifying its type. In the same way concerning enumerations, you can declare a variable and, to indicate that it is bound to an enumeration, initialize the variable using a member of the enumeration. Here is an example:

```type Category =
| Teen
| Senior

In the same way, you can access any member of the enumeration in your code. Here are example:

```type Category =
| Teen
| Senior

if membership = Teen then
printfn "Membership Category: Teen";
elif membership = Senior then
printfn "Membership Category: Senior";```

This would produce:

```Membership Category: Adult
Press any key to continue . . .```

An Enumeration as a Type

When declaring a variable for an enumeration, if you want, you can specify the data type of a variable. As always, to do this, after the name of the variable, type a colon followed by the name of the enumeration. Here is an example:

```type Category =
| Teen
| Senior

let membership : Category = Adult;```

Qualifying an Enumeration Member

When accessing a member of an enumeration, you can explicitly indicate the enumeration to which the member belongs. To do this, type the name of the enumeration, a period, and the name of the desired member of the enumeration. Here are examples:

```type Category =
| Teen
| Senior

if membership = Category.Teen then
printfn "Membership Category: Teen";
elif membership = Category.Senior then
printfn "Membership Category: Senior";```

That technique is referred to as qualifying the member of the enumeration, and it can make your code easier to read.

The Values of Members of an Enumeration

An enumeration contains members whose names actually represent some constant values. The numeric value for a member can be any natural number you want. In fact, you can specify the value of each member as you want. To do this, assign the desired number to each member of the enumeration. The formulat to use is:

```type EnumerationName =
| MemberName1 [ = IntegralValue1 ]
| MemberName2 [ = IntegralValue2 ] ]
| MemberName_n [ = IntegralValue_n ]```

As you saw in the beginning, you don't have to specify the values of the members of an enumeration; but unlike other languages such as C/C++ or C#, if you decide to give values, you must assign a number to each member of the enumeration. Here are examples:

```type Category =
| Teen = 10
| Senior = 30

if membership = Category.Teen then
printfn "Membership Category: Teen";
elif membership = Category.Senior then
printfn "Membership Category: Senior";```

Remember that you can assign any value you want to each member of the enumeration but the values must be integers or characters of type sbyte, byte, int16, uint16, int32, uint32, int64, uint16, uint64, or char.

Enumerations and Functions

Introduction

Since an enumeration is primarily a type, you can use it like the other types we have used si far. For example, in the body of a function, you can declare a variable of an enumeration type and then use it as you see fit. Here is a simple example:

```type Category =
| Teen
| Senior

let processMembership _ =

if membership = Teen then
printfn "Membership Category: Teen";
elif membership = Senior then
printfn "Membership Category: Senior";

processMembership()```

A Parameter as an Enumeration

A parameter of a function can be an enumeration. To start, you can provide a parameter with a name. In the function, use the parameter with values that are its members.. When calling the function, pass an argument whose value is one of the members of the enumeration. Here is an example:

```type Category =
| Teen
| Senior

let processMembership cat =
if cat = Teen then
printfn "Membership Category: Teen";
elif cat = Senior then
printfn "Membership Category: Senior";

let membership = Teen;
processMembership membership```

This would produce:

```Membership Category: Teen

Press any key to close this window . . .```

Returning an Enumeration

You can create a function that returns a value that is a member of an enumeration. To do this, in the body of the function, process whatever is necessary. In the last line of the function, make sure you return a value that is a member of the enumeration. If you are usiing conditional statements, make sure each condition returns a member of the enumeration.Here is an example:

```type Category =
| Teen
| Senior

let validate nbr =
if nbr <= 17 then
Teen
elif nbr <= 55 then
else
Senior

let processMembership cat =
if cat = Teen then
printfn "Membership Category: Teen";
elif cat = Senior then
printfn "Membership Category: Senior";

let membership = validate 62
processMembership membership```

This would produce:

```Membership Category: Senior

Press any key to close this window . . .```

Enumerations and Classes

An Enumeraion as a Field Type

A locally-declared let variable of a class can come from an enumeration. The variable is declared like any other. To proceed, use the let to declare the variable and assign a value to the variable. The value you assign to the variable must be a recognizable member of the enumeration. If the enumeration and the class are created in the same document, you can simply assign the desired member of the enumeration to the variable. Here is an example:

```type TempoType =
| Slow
| Medium
| Fast

type Song() =
let bits = 63
let temp = Medium```

Once you have done that, a method or a do binding in the class that access the variable. If you want to display its value, you can cast it with let. Here is an example:

```type TempoType =
| Slow
| Medium
| Fast

type Song() =
let bits = 63
let temp = Medium

do
printfn "Song Characteristics"
printfn "---------------------"
printfn "Tempo Type: %s" (string temp)
printfn "Bits:       %i" bits

let sng = Song()```

This would produce:

```Book Characteristics
----------------------------------------------------------
Title:           Fundamentals of Web Graphics with Python
Cover Type:      Soft
Language:        English
Number of Pages: 588
==========================================================

Press any key to close this window . . .```

To make your code easy to read and eliminate some confusions, you should specify the data type of the variable by applying the name of the enumeration to it. This can be done as follows:

```type TempoType =
| Slow
| Medium
| Fast

type Song() =
let bits = 63
let temp : TempoType = Medium```

Enumerations and Methods

An enumeration can be used on both sides of a method. As seen with functions, you can create a method that uses a parameter of an enumeration type; and you can create a method that returns an enumeration member.

Enumerations and Properties

A property of a class can be created from an enumeration. If you are creating read-only property, give the desird name to the member property and you can assign any value to it. Consider the following example:

```type Book(cover, title, pages) =
member me.Title with get() = title
member me.Envelop with get() = cover
member me.Language = "English"
member me.NumberOfPages = pages```

Notice that, in this generic code, there is nothing that suggests the presence of any enumeration. When declaring a varia for the class, if you want a parameter to be related to an enumeration, you must pass an argument that holds the name of one of the members of an enumeration. After that, the enumeration is used. Of course, the compiler must be able to find that value, which is easy if the enumeration is created in the same document as the class. Here is an example:

```type Cover =
| Soft
| Paperback
| Hardback

type Book(cover, title, pages) =
member me.Title with get() = title
member me.Envelop with get() = cover
member me.Language = "English"
member me.NumberOfPages = pages

let reading = Book(Soft, "Fundamentals of Web Graphics with Python", 588)

printfn "Book Characteristics"
printfn "----------------------------------------------------------"
printfn "Cover Type:      %s" (string reading.Envelop)
printfn "Number of Pages: %i" reading.NumberOfPages
printfn "=========================================================="```

This would produce:

```Book Characteristics
----------------------------------------------------------
Title:           Fundamentals of Web Graphics with Python
Cover Type:      Soft
Language:        English
Number of Pages: 588
==========================================================

Press any key to close this window . . .```

Write-Only Properties

In a class, you can create a write-only property that is of an enumeration type. To proceed, declare a mutable variable and initialize it with a member of the enumertion. Still in the class, create a set()-only member property and assign value to its associated mutable variable. This can be done as follows:

```type Cover =
| Soft
| Paperback
| Hardback
| Unknown

type Book() =
let mutable cover = Unknown
. . .

member me.Envelop with set(value) = cover <- value```

Outside the class, declare a variable of that class, use the <- operator to assign the desired value to the property. Here is an example:

```type Cover =
| Soft
| Paperback
| Hardback
| Unknown

type Book() =
let mutable cover = Unknown
let mutable title = ""
let mutable lang = ""
let mutable pages = 0

member me.Show _ =
printfn "Book Characteristics"
printfn "----------------------------------------------------------"
printfn "Title:           %s" title
printfn "Cover Type:      %s" (string cover)
printfn "Language:        %s" lang
printfn "Number of Pages: %i" pages

member me.Title with set(value) = title <- value
member me.Envelop with set(value) = cover <- value
member me.Language with set(value) = lang <- value
member me.NumberOfPages with set(value) = pages <- value

reading.Title   <- "Fundamentals of Web Graphics with Python"