# Chapter 7: Modules

As programs grow, you need to split code across files. Lux has a module system for organizing and sharing code.

## Module Basics

Every `.lux` file is a module. The file path determines the module path:

```
project/
├── main.lux           # Module: main
├── utils.lux          # Module: utils
└── lib/
    ├── math.lux       # Module: lib/math
    └── strings.lux    # Module: lib/strings
```

## Importing Modules

### Basic Import

```lux
import lib/math

fn main(): Unit with {Console} = {
    Console.print(toString(lib/math.square(5)))
}
```

Wait, that's verbose. Use an alias:

### Aliased Import

```lux
import lib/math as math

fn main(): Unit with {Console} = {
    Console.print(toString(math.square(5)))
}
```

### Selective Import

Import specific items directly:

```lux
import lib/math.{square, cube}

fn main(): Unit with {Console} = {
    Console.print(toString(square(5)))   // No prefix needed
    Console.print(toString(cube(3)))
}
```

### Wildcard Import

Import everything:

```lux
import lib/math.*

fn main(): Unit with {Console} = {
    Console.print(toString(square(5)))
    Console.print(toString(cube(3)))
    Console.print(toString(factorial(6)))
}
```

Use sparingly—it can cause name conflicts.

## Visibility

By default, declarations are private. Use `pub` to export:

```lux
// lib/math.lux

// Public - can be imported
pub fn square(x: Int): Int = x * x

pub fn cube(x: Int): Int = x * x * x

// Private - internal helper
fn helper(x: Int): Int = x + 1

// Public type
pub type Point = { x: Int, y: Int }
```

## Creating a Module

Let's create a string utilities module:

```lux
// lib/strings.lux

/// Repeat a string n times
pub fn repeat(s: String, n: Int): String =
    if n <= 0 then ""
    else s + repeat(s, n - 1)

/// Check if string starts with prefix
pub fn startsWith(s: String, prefix: String): Bool =
    String.startsWith(s, prefix)

/// Check if string ends with suffix
pub fn endsWith(s: String, suffix: String): Bool =
    String.endsWith(s, suffix)

/// Pad string on the left to reach target length
pub fn padLeft(s: String, length: Int, char: String): String = {
    let current = String.length(s)
    if current >= length then s
    else padLeft(char + s, length, char)
}

/// Pad string on the right to reach target length
pub fn padRight(s: String, length: Int, char: String): String = {
    let current = String.length(s)
    if current >= length then s
    else padRight(s + char, length, char)
}
```

Using it:

```lux
// main.lux
import lib/strings as str

fn main(): Unit with {Console} = {
    Console.print(str.repeat("ab", 3))       // "ababab"
    Console.print(str.padLeft("5", 3, "0"))  // "005"
}

let output = run main() with {}
```

## Module Organization Patterns

### Feature Modules

Group by feature:

```
project/
├── main.lux
├── users/
│   ├── types.lux      # User type definitions
│   ├── repository.lux # Database operations
│   └── service.lux    # Business logic
├── orders/
│   ├── types.lux
│   ├── repository.lux
│   └── service.lux
└── shared/
    ├── utils.lux
    └── effects.lux
```

### Layer Modules

Group by layer:

```
project/
├── main.lux
├── domain/           # Business logic (pure)
│   ├── user.lux
│   └── order.lux
├── effects/          # Effect definitions
│   ├── database.lux
│   └── email.lux
├── handlers/         # Effect implementations
│   ├── postgres.lux
│   └── smtp.lux
└── api/              # Entry points
    └── http.lux
```

## Standard Library

Lux has a standard library in the `std/` directory:

```lux
import std/prelude.*    // Common utilities
import std/option       // Option helpers
import std/result       // Result helpers
import std/io           // I/O utilities
```

### std/prelude

```lux
import std/prelude.*

identity(42)           // 42
compose(f, g)          // Function composition
not(true)              // false
and(true, false)       // false
or(true, false)        // true
```

### std/option

```lux
import std/option as opt

opt.some(42)                    // Some(42)
opt.none()                      // None
opt.map(Some(5), double)        // Some(10)
opt.flatMap(Some(5), safeDivide)
opt.unwrapOr(None, 0)           // 0
```

### std/result

```lux
import std/result as res

res.ok(42)                      // Ok(42)
res.err("oops")                 // Err("oops")
res.mapOk(Ok(5), double)        // Ok(10)
res.mapErr(Err("x"), upper)     // Err("X")
```

## Circular Dependencies

Lux detects circular imports:

```lux
// a.lux
import b
pub fn fromA(): Int = b.fromB() + 1

// b.lux
import a
pub fn fromB(): Int = a.fromA() + 1

// Error: Circular dependency detected
```

Solution: extract shared code to a third module.

## Module Best Practices

### 1. One Concept Per Module

```lux
// Good: focused module
// user.lux - User type and operations
pub type User = { id: Int, name: String }
pub fn createUser(name: String): User = ...
pub fn validateUser(u: User): Bool = ...

// Bad: kitchen sink
// utils.lux - random stuff
pub fn parseUser(s: String): User = ...
pub fn formatDate(d: Date): String = ...
pub fn calculateTax(amount: Int): Int = ...
```

### 2. Export Deliberately

```lux
// Only export what others need
pub fn publicApi(): Result = ...

// Keep helpers private
fn internalHelper(): Int = ...
```

### 3. Use Aliases for Clarity

```lux
// Clear what comes from where
import database/postgres as db
import cache/redis as cache

fn getData(id: Int): Data with {Database, Cache} = {
    match cache.get(id) {
        Some(d) => d,
        None => {
            let d = db.query(id)
            cache.set(id, d)
            d
        }
    }
}
```

### 4. Group Related Imports

```lux
// Standard library
import std/prelude.*
import std/option as opt

// Project modules
import lib/database as db
import lib/cache as cache

// Local modules
import ./types.{User, Order}
import ./validation
```

## Summary

| Syntax | Meaning |
|--------|---------|
| `import path/to/module` | Import module |
| `import path/to/module as alias` | Import with alias |
| `import path/to/module.{a, b}` | Import specific items |
| `import path/to/module.*` | Import all exports |
| `pub fn` / `pub type` | Export declaration |

## Next

[Chapter 8: Error Handling](08-errors.md) - Handling failures gracefully.
