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
| Concept | JavaScript/JSON | Hot |
|---|---|---|
| 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 string | N/A | """...""" (no escaping, indent-aware) |
| Block template string | N/A | ```...``` (indent-aware ${} interpolation) |
| Integer | 42 | 42 (same!) |
| Float | 3.14 | 3.14 (but it's Dec!) |
| Boolean | true/false | true/false (same!) |
| Null | null | null (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,Mapfor key-value collections- Use
Decfor 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