<!-- Sema documentation — std.cache
     Sema is a new AI-native, neurosymbolic programming language most models
     have not been trained on. Full corpus: https://sema.49.12.246.95.sslip.io/llms-full.txt
     Install language support: https://sema.49.12.246.95.sslip.io/install-skill/ -->

# std.cache

> Memoization as ordinary Sema decorators — memoize caches within a run, memoize_disk persists across runs.

`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.

```sema
from std.cache import memoize, memoize_disk
```

## 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

`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}`:

```sema
@memoize
def embed(text: str) -> list[f64] !{model.invoke}:
    return semantic.embed(text)

a = embed("hello")   # computes
b = embed("hello")   # cache hit — no second model call
```

The 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

`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}`:

```sema
@memoize_disk
def fetch_report(url: str) -> str !{net.connect}:
    return http.get(url)

# First run writes .sema/cache/<hash>.json; later runs read it back.
```

:::note[When to use disk vs. in-run]
Reach for `memoize` for within-run reuse (embeddings, repeated sub-queries), and
`memoize_disk` when a result is expensive *and* worth keeping between runs (a
fetched document, a slow model synthesis). Because the disk cache is JSON, the
result must be JSON-serializable.
:::

:::tip[Decorators are just functions]
Any Sema function is a decorator, and a decorator resumes the wrapped call with
`call(fn, args)`. `memoize` is only ~7 lines of Sema — read it and copy the
pattern to build a TTL or namespaced variant of your own.
:::

See the exact signatures and effect rows in the generated
[std.cache API reference](/reference/stdlib-api/cache/).
