Skip to content

box module

A box is a tiny mutable cell that holds a single value. It provides reference-like semantics without language-level pointers. Use it when you want to share and mutate a value across functions, or avoid copying large values.

  • Import: import box
  • Backing: A box is implemented as a one-element array internally.
  • Pattern: Get/transform/Set via explicit functions.

API

  • box.New(value any) (box, error)
  • Create a new box containing value.
  • box.Get(b box) (value, error)
  • Read the value stored in the box.
  • box.Set(b box, value any) (None, error)
  • Replace the value in the box with value.

All functions return (result, error) tuples consistent with Harneet stdlib conventions.

Why use a box?

  • Pass-by-reference semantics without references:
  • Let a callee update a caller’s value.
  • Shared mutable state:
  • Multiple functions can observe and update a single, shared slot.
  • Large values:
  • Pass a small handle (the box) rather than copying/rebinding large data repeatedly.

When to use in the real world

  • Counters, accumulators, and state shared across helpers.
  • Swapping values across two locations.
  • Coordinating state across callbacks or closures.
  • Managing large data held in memory (e.g., a full file’s contents) when a single shared value needs mutation.
  • Note: For very large data processing, prefer streaming or chunked processing via the file module if you don’t need the entire data in memory.

Examples

Basic usage

package main
import fmt
import box

// Create a box holding an integer
var counterBox, err = box.New(0)
if err != None {
    fmt.Println("box.New error:", err)
}

// Read
var value, err1 = box.Get(counterBox)
if err1 == None {
    fmt.Println("initial value:", value)
}

// Write
var _, err2 = box.Set(counterBox, 42)
if err2 == None {
    var newValue, _ = box.Get(counterBox)
    fmt.Println("updated value:", newValue)  // 42
}

Pass-by-reference style mutation

package main
import fmt
import box

function Increment(b any) {
    var v, err = box.Get(b)
    if err != None {
        fmt.Println("box.Get error:", err)
        return
    }
    var _, setErr = box.Set(b, v + 1)
    if setErr != None {
        fmt.Println("box.Set error:", setErr)
        return
    }
}

var counter, e = box.New(10)
if e == None {
    Increment(counter)
    var v, _ = box.Get(counter)
    fmt.Println("after increment:", v)  // 11
}

Swap using boxes (shared mutable state)

package main
import fmt
import box

function Swap(a any, b any) {
    var av, errA = box.Get(a)
    if errA != None { return }

    var bv, errB = box.Get(b)
    if errB != None { return }

    var _, errSetA = box.Set(a, bv)
    if errSetA != None { return }

    var _, errSetB = box.Set(b, av)
    if errSetB != None { return }
}

var x, _ = box.New(1)
var y, _ = box.New(2)
Swap(x, y)
var xv, _ = box.Get(x)
var yv, _ = box.Get(y)
fmt.Println("x:", xv, "y:", yv)  // x: 2 y: 1

Large data in a box

package main
import fmt
import box
import file
import strings

// Read a full file (for demo). For very large files, consider streaming.
var content, readErr = file.Read("README.md")
if readErr == None {
    var contentBox, err = box.New(content)
    if err == None {
        var current, _ = box.Get(contentBox)
        var updated = current + "\n---\nprocessed by box example\n"
        var _, setErr = box.Set(contentBox, updated)
        if setErr == None {
            var final, _ = box.Get(contentBox)
            var length, lenErr = strings.Len(final)
            if lenErr == None {
                fmt.Println("content length:", length)
            }
        }
    }
}

Remember this →

  • Treat a box like a tiny heap-allocated cell holding one value.
  • Don’t overuse boxes; prefer pure functions and returning updated values when mutation isn’t needed.
  • Boxes are excellent when you need a shared, mutable slot or pass-by-reference semantics.