Light Dark

Data Literals

Hot uses JavaScript-like syntax for data literals, making it instantly familiar if you've worked with JSON. There are a few important differences to be aware of.

Strings

Double-quoted strings, just like JSON:

greeting "Hello, world!"
path "/api/users"
empty-str ""

Template Strings

Use backticks for string interpolation:

name-tpl "Alice"
message `Hello, ${name-tpl}!`              // "Hello, Alice!"
calculation `2 + 2 = ${add(2, 2)}`         // "2 + 2 = 4"
`Hello, ${name}!`        → "Hello, Alice!"
`2 + 2 = ${add(2, 2)}`   → "2 + 2 = 4"

Any expression can go inside ${}.

Block Strings

For content where you don't want escape processing, use block strings ("""):

simple-tq """Hello, world!"""

multiline-tq """
    SELECT *
    FROM users
    WHERE active = true
    """

Block strings have no escape processing — escape sequences (\n, \", etc.) are not interpreted, so characters are treated as literal text. They're also indent-aware: the closing """ determines the base indentation, which is automatically stripped from all lines. This makes them ideal for documentation, SQL queries, HTML templates, and embedded code examples.

Block Template Strings

For multi-line content that needs both indent-awareness and ${} interpolation, use block template strings:

table-name "users"
max-rows 100
query-tbt ```
    SELECT * FROM ${table-name}
    WHERE active = true
    LIMIT ${max-rows}
    ```

Block template strings combine the best of both worlds: indent-aware like block strings (the closing ``` determines the base indentation to strip) and interpolation like template strings (${} expressions are evaluated). Like block strings, they have no escape processing. This makes them ideal for shell scripts, HTML templates, and embedded code that needs Hot variables.

Numbers

Hot has two number types: Int and Dec.

Int (Integers)

Whole numbers without decimal points:

count-num 42
negative -17
zero-num 0

Dec (Decimals)

Numbers with decimal points. Hot uses Dec instead of floating-point:

price 19.99
rate 0.05
pi 3.14159265358979323846

Why Dec instead of Float?

Floating-point math has precision issues:

// In JavaScript: 0.1 + 0.2 = 0.30000000000000004

Hot's Dec type uses 256-bit decimal arithmetic (via fastnum D256) providing up to 76 digits of precision. This means exact decimal arithmetic—critical for money, percentages, scientific calculations, and anywhere precision matters.

// These are exact in Hot, no floating-point errors
total-dec add(0.1, 0.2)   // Exactly 0.3
add(0.1, 0.2) → 0.3  // Exact, no floating-point error!

Booleans

active true
disabled false

Null

The absence of a value:

nothing null
user-avatar null

Vectors

Ordered collections using square brackets:

numbers [1, 2, 3]
names ["Alice", "Bob", "Carol"]
mixed ["text", 42, true, null]
empty-vec []

Nested vectors:

matrix [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
]

Access elements with first(), last(), or index notation:

numbers-access [10, 20, 30]
first-num first(numbers-access)   // 10
last-num last(numbers-access)     // 30

Note: Hot uses Vec (vector) where other languages use "array". Same concept, different name.

Vec Spread

Use ... to flatten existing vectors into a new vector literal:

a [1, 2, 3]
b [4, 5]
combined [...a, ...b]           // [1, 2, 3, 4, 5]
with-extras [0, ...a, 99]      // [0, 1, 2, 3, 99]
clone [...a]                    // [1, 2, 3] (shallow copy)

Spread elements are flattened inline. Non-spread elements and spread elements can be freely mixed. For simple concatenation without extra elements, you can also use concat(a, b).

Maps (like Objects)

Key-value collections using curly braces:

user-map {name: "Alice", age: 30}
config-map {debug: true, port: 8080}
empty-map {}

Nested maps:

settings {
  database: {
    host: "localhost",
    port: 5432
  },
  cache: {
    enabled: true,
    ttl: 3600
  }
}

Access properties with dot notation:

user-access {name: "Alice", email: "alice@example.com"}
name-access user-access.name     // "Alice"
email-access user-access.email   // "alice@example.com"
user.name  → "Alice"
user.email → "alice@example.com"

Map vs Object: Hot calls these Map instead of Object. Keys are always strings.

Map Spread

Use ... to merge existing maps into a new map literal:

defaults {timeout: 5000, retries: 3}
config {...defaults, retries: 5}    // {timeout: 5000, retries: 5}

Later keys win, so spread entries can be selectively overridden. Multiple spreads and explicit keys can be mixed in any order.

Comparison to JavaScript/JSON

ConceptJavaScript/JSONHot
Array[1, 2, 3][1, 2, 3] (same syntax, called Vec)
Object{"a": 1}{a: 1} (unquoted keys, called Map)
String"hello""hello" (same!)
Template string`Hi ${name}``Hi ${name}` (same!)
Block stringN/A"""...""" (no escaping, indent-aware)
Block template stringN/A```...``` (indent-aware ${} interpolation)
Integer4242 (same!)
Float3.143.14 (but it's Dec!)
Booleantrue/falsetrue/false (same!)
Nullnullnull (same!)

Type Annotations on Literals

You can add types to your data for documentation and type checking:

// Simple types
count-typed: Int 42
price-typed: Dec 19.99
name-str: Str "Alice"

// Generic types
numbers-typed: Vec<Int> [1, 2, 3]
prices-typed: Vec<Dec> [9.99, 19.99]
user-typed: Map<Str, Any> {name: "Alice", age: 30}

Summary

  • Hot's data literals are nearly identical to JSON
  • Vec (vector) for ordered collections, Map for key-value collections
  • Use Dec for decimals (not floating-point) — exact precision
  • Template strings use backticks with ${expression} interpolation
  • Block strings ("""...""") — no escape processing, indent-aware
  • Block template strings (```...```) for indent-aware content with ${} interpolation
  • Access vectors with [index], maps with .property