F# by example
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Organization

Code organization is a crucial aspect of software development and it is essential to choose the right tools to ensure that your code is well-structured, maintainable, and scalable. In F#, modules and namespaces are two of the tools that are commonly used to achieve code organization.

Choosing between Modules and Namespaces

// Choosing between Modules and Namespaces

// When deciding between using modules or namespaces for code organization, it is important to consider the purpose of each tool and to choose the one that best fits your needs.

// When to use modules?
// If you need to group related functions, types, and values into a single unit, then modules are the better choice. Modules provide a way to encapsulate implementation details and to improve code reusability.

// Example:

module MyModule

// Define functions
let add x y = x + y
let subtract x y = x - y
let multiply x y = x * y
let divide x y = x / y

// Define a list named "mathOperations" that contains all four functions defined above
let mathOperations = [add; subtract; multiply; divide]

// Define a function named "processOperations" that takes two arguments "x" and "y"
// and returns the result of each of the four functions in the "mathOperations" list for the given inputs
let processOperations x y =
    mathOperations
    |> List.map (fun operation -> operation x y)

// When to use namespaces?
// If you need to group types together and avoid naming conflicts, then namespaces are the better choice. Namespaces provide a way to organize code into logical units and to make it easier to manage your code as it grows.

namespace Math

// Define a type named "Calculator" within the "Math" namespace
type Calculator =
    static member Add (x: int, y: int) = x + y
    static member Subtract (x: int, y: int) = x - y
    static member Multiply (x: int, y: int) = x * y
    static member Divide (x: int, y: int) = x / y

namespace Utils

// Define a type named "Calculator" within the "Utils" namespace
type Calculator =
    static member ConvertToFahrenheit (c: float) = (c * 9.0 / 5.0) + 32.0
    static member ConvertToCelsius (f: float) = (f - 32.0) * 5.0 / 9.0

⬇️ modules_vs_namespaces.fsx

> #load "modules_vs_namespaces.fsx";;
> open Modules_vs_namespaces;;
// Access the module members from MyModule
> MyModule.add 10 5;;
val it : int = 15

> MyModule.divide 20 4;;
val it : int = 5

// Access the Calculator type from the Math namespace
> Math.Calculator.Add(5, 3);;
val it : int = 8

> Math.Calculator.Multiply(4, 6);;
val it : int = 24

// Access the Calculator type from the Utils namespace
> Utils.Calculator.ConvertToFahrenheit(25.0);;
val it : float = 77.0

> Utils.Calculator.ConvertToCelsius(98.6);;
val it : float = 37.0

Comparison Table

To help you make an informed decision when choosing between modules and namespaces for code organization, we have provided a comparison table that summarizes the key differences between the two tools.

ModulesNamespaces
Can contain functions, types, and valuesCan only contain types
Encapsulate implementation detailsOrganize code into logical units
Improve code reusabilityAvoid naming conflicts between types
Provide a way to organize code into logical units