with one click
with one click
Nim testing conventions, unittest framework, and C++ compatibility patterns
Nim bindings to libtorch for tensor operations with high-level sugar
Nim type system patterns and pitfalls
Common import patterns and pitfalls for the Tattletale Nim project
Regex functionality in Nim including std/re, std/nre wrappers around PCRE, and the pure Nim nim-regex alternative with linear-time matching guarantees
Nim to Python interoperability including nimpy for calling Python from Nim and exporting Nim to Python, nimporter for packaging Nim modules as Python packages, and cffi/ctypes for calling Nim from Python
| name | tables |
| description | Nim's hash table module for key-value storage |
| license | MIT |
| compatibility | opencode |
| metadata | {"audience":"nim-developers","use-case":"data-structures"} |
tables ModuleThe tables module provides hash table implementations for key-value storage in Nim.
Table[A, B] - Standard hash table (value semantics, copies on assignment)TableRef[A, B] - Reference-based hash table (shared on assignment)OrderedTable[A, B] - Preserves insertion orderCountTable[A] - Maps keys to occurrence countsimport std/tables
# Create empty table
var t = initTable[string, int]()
t["key"] = 42
# Create from pairs literal
let t2 = {"a": 1, "b": 2}.toTable
# TableRef for ref semantics (shared state)
let ref_t = newTable[string, int]()
ref_t["key"] = 42
# Insert or update
t["key"] = 42
# Access (raises KeyError if missing)
let val = t["key"]
# Check if key exists
if t.hasKey("key"):
discard
# Get with default value
let val = t.getOrDefault("key", 0)
# Atomic check-and-set
if t.hasKeyOrPut("key", defaultValue):
# key already existed
else:
# key was just inserted
# Get or modify
discard t.mgetOrPut("key", defaultValue)
t["key"] = t["key"] + 1
# Delete (does nothing if missing)
t.del("key")
# Length
echo t.len
Use pairs, keys, and values iterators to traverse tables:
for k, v in t.pairs:
echo "key: ", k, " value: ", v
for k in t.keys:
echo "key: ", k
for v in t.values:
echo "value: ", v
# For mutable tables, use mpairs/mvalues to modify in place
for k, v in t.mpairs:
v = v + 1
Preserves insertion order (unlike regular Table):
import std/tables
var ot = initOrderedTable[string, int]()
ot["z"] = 1
ot["a"] = 2
ot["m"] = 3
# Iteration follows insertion order: z, a, m
for k, v in ot.pairs:
echo k, " -> ", v
Counts occurrences (useful for frequency analysis):
import std/tables
# Create from sequence
var ct = toCountTable("abracadabra")
# Result: {'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1}
# Increment count
ct.inc('x')
ct.inc('y', 5) # increment by 5
# Get count (returns 0 if missing)
echo ct['a'] # 5
# Sort by frequency
ct.sort() # descending by default
template withValue*[A, B](t: var Table[A, B], key: A, value, body: untyped) =
## Retrieves value at t[key] if it exists, binds to `value`
mixin rawGet
var hc: Hash
var index = rawGet(t, key, hc)
let hasKey = index >= 0
if hasKey:
var value {.inject.} = addr(t.data[index].val)
body
# Usage
t.withValue("mykey", val):
echo "Found: ", val
do:
echo "Key not found"
var result = ct1
for k, v in ct2:
result.inc(k, v)
| Feature | Table | TableRef |
|---|---|---|
| Assignment | Copies entire table | Shares reference |
| Memory | Each copy is independent | All refs point to same data |
| Use when | Isolation needed | Shared mutable state |
hash proc for keys - works with int, string, and custom types with defined hash procpairs iterator returns (key, value) tuples - use toSeq() to convert to seqOrderedTable uses more memory but preserves insertion orderCountTable uses zero as sentinel, so count of 0 means "empty slot"