Skip to content

When to Use Each Type

Before modelling a domain, it is worth reviewing which type solves each problem most directly. The example below demonstrates all types in realistic situations:

Cheatsheet: array, set, map, tuple, struct, enum, newtype, and enum with data.

12-when-to-use.zolo
Playground
// Feature: Cheatsheet — when to use which collection/type

// Syntax: various — this file demonstrates choosing the right

// structure for the right problem.

// When to use: review concepts before modeling a domain.


use std::String
use std::Map
use std::Set

// 1) ARRAY — when order matters and there are legitimate duplicates.

let log_lines = ["start", "tick", "tick", "stop"]
print(log_lines.len())  // 4


// 2) SET — when you only want to know "is it in or not".

let visited = Set::new()
visited.add("/home")
visited.add("/about")
visited.add("/home")  // duplicate ignored

print(visited.len())  // 2


// 3) MAP — key lookup, counting, configuration.

let prices = #{banana: 3, apple: 5, orange: 4}
print(prices["banana"])  // 3


// 4) TUPLE (= array with destructure) — lightweight grouping, multi-return.

fn split_name(full: str) -> [str] {
  let parts = full.split(" ")
  return [parts[0], parts[1]]
}

let (first, last) = split_name("Alice Silva")
print("{first} / {last}")

// 5) STRUCT — when fields have NAMES and the domain is stable.

struct User {
  name: str,
  age: int,
}

let u = User { name: "Bob", age: 25 }
print("{u.name} ({u.age})")

// 6) ENUM — when the value is "one of these mutually exclusive shapes".

enum HttpMethod {
  Get,
  Post,
  Put,
  Delete,
}

fn safe(m: HttpMethod) -> bool {
  return match m {
    HttpMethod::Get => true,
    HttpMethod::Post => false,
    HttpMethod::Put => false,
    HttpMethod::Delete => false,
  }
}

print(safe(HttpMethod::Get))  // true

print(safe(HttpMethod::Post))  // false


// 7) NEWTYPE — when two types have the SAME physical shape but

// must be distinct in the domain (IDs, units).

newtype CustomerId(int)
newtype InvoiceId(int)
let cid = CustomerId.new(10)
let iid = InvoiceId.new(20)

fn use_ids(c: CustomerId, i: InvoiceId) {
  print("c={c.unwrap()} i={i.unwrap()}")
}

use_ids(cid, iid)

// 8) ENUM with data — sum types (ADT). Ideal for AST,

// messages, parsing.

enum Json {
  Num(float),
  Str(str),
  Bool(bool),
  Null,
}

fn show(j: Json) -> str {
  return match j {
    Json::Num(n) => "num({n})",
    Json::Str(s) => "str({s})",
    Json::Bool(b) => "bool({b})",
    Json::Null => "null",
  }
}

print(show(Json::Num(3.14)))
print(show(Json::Str("hi")))
print(show(Json::Bool(true)))
print(show(Json::Null))

Golden-rule summary:

Situation Type
Ordered list, duplicates allowed [T] (array)
Membership, no duplicates Set
Key → value, lookup by key Map
2–3 unnamed values, multiple return tuple (let (a, b) = ...)
Named fields, stable domain struct
Value is "one of N shapes" enum
Two types with the same physical format, distinct in the domain newtype
enespt-br