std.cache
std.cache provides memoization as a decorator. Apply @memoize to any
function and its result is cached by (callee, arguments) for the duration of the
run. It is the everyday way to avoid recomputing an expensive step — a model call,
an embedding, a fetch — that you know is pure for its inputs.
from std.cache import memoize, memoize_diskWhy it exists
Section titled “Why it exists”Caching an expensive AI step is universal, and hand-rolled caches drift into
bespoke pickle paths and ad-hoc keys (a typical hand-rolled cache_or_load pickle
layer). std.cache standardizes it, and because it is written in Sema as an
ordinary decorator, you can write your own variants (TTL, namespacing) the same
way — no framework hooks required.
memoize — cache within a run
Section titled “memoize — cache within a run”memoize keys on the callee and its arguments and stores results in the ambient
memory store, so its effect row is !{memory.read, memory.write}:
@memoizedef embed(text: str) -> list[f64] !{model.invoke}: return semantic.embed(text)
a = embed("hello") # computesb = embed("hello") # cache hit — no second model callThe decorated function’s own effects still apply the first time it runs; the cache only short-circuits repeats within the same process.
memoize_disk — persist across runs
Section titled “memoize_disk — persist across runs”memoize_disk JSON-encodes each result under .sema/cache/<hash>.json, keyed by
(callee, arguments), so the cache survives process restarts. Its effect row is
!{fs.read, fs.write}:
@memoize_diskdef fetch_report(url: str) -> str !{net.connect}: return http.get(url)
# First run writes .sema/cache/<hash>.json; later runs read it back.See the exact signatures and effect rows in the generated std.cache API reference.