Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

v0 source pure

Package memo provides a simple memoization utility to cache function results.

Readme View source

gno.land/p/moul/memo/v0

A simple memoization utility to cache function results, backed by a B+ tree (gno.land/p/nt/bptree).

A B+ tree packs many entries per persisted node, so it costs materially less storage and gas per cached entry than an AVL backing would.

 1import "gno.land/p/moul/memo/v0"
 2
 3m := memo.New()
 4
 5// Cache expensive computation; subsequent calls with the same key
 6// return the cached result without re-running the function.
 7result := m.Memoize("key", func() any {
 8	return "computed-value"
 9})
10
11m.Invalidate("key") // drop one entry
12m.Clear()           // drop all entries
13m.Size()            // number of cached entries

⚠️ Gno usage: storage updates only persist during transactions. Memoizing during queries/render will not persist and only wastes resources — use this in transaction-driven contexts.

Caveats from the B+ tree backing: it mutates in place (a copy-on-write AVL backing would not), so do not Invalidate/add entries from inside a callback iterating the same Memoizer, and do not copy a non-zero Memoizer by value.


Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.

Dependency graph:

gno.land/p/moul/memo/v0 dependency graph

⚠️ Disclaimer: provided as-is, without warranty; not security-audited. Full disclaimer: DISCLAIMER.

Overview

Package memo provides a simple memoization utility to cache function results.

The package offers a Memoizer type that can cache function results based on keys, with optional validation of cached values. This is useful for expensive computations that need to be cached and potentially invalidated based on custom conditions.

It is the B+ tree successor to gno.land/p/moul/memo/v0 (which is backed by an AVL tree): a bump to v3 because the backing data structure — and thus the on-chain storage layout — changed. The exported API is identical to v2 (New/Memoize/MemoizeWithValidator/Invalidate/Clear/Size). A B+ tree packs many entries per persisted node, so it costs materially less storage and gas per cached entry — prefer v3 when the cache is part of persisted realm state.

Because the B+ tree backing mutates in place (the AVL backing was copy-on-write), do NOT invalidate or add entries to the same Memoizer from inside a callback that is iterating it, and do NOT copy a non-zero Memoizer by value.

/!\ Important Warning for Gno Usage: In Gno, storage updates only persist during transactions. This means:

  • Cache entries created during queries will NOT persist
  • Creating cache entries during queries will actually decrease performance as it wastes resources trying to save data that won't be saved

Best Practices: - Use this pattern in transaction-driven contexts rather than query/render scenarios - Consider controlled cache updates, e.g., by specific accounts (like oracles) - Ideal for cases where cache updates happen every N blocks or on specific events - Carefully evaluate if caching will actually improve performance in your use case

Basic usage example:

Example
 1m := memo.New()
 2
 3// Cache expensive computation
 4result := m.Memoize("key", func() any {
 5    // expensive operation
 6    return "computed-value"
 7})
 8
 9// Subsequent calls with same key return cached result
10result = m.Memoize("key", func() any {
11    // function won't be called, cached value is returned
12    return "computed-value"
13})

Example with validation:

Example
 1type TimestampedValue struct {
 2    Value     string
 3    Timestamp time.Time
 4}
 5
 6m := memo.New()
 7
 8// Cache value with timestamp
 9result := m.MemoizeWithValidator(
10    "key",
11    func() any {
12        return TimestampedValue{
13            Value:     "data",
14            Timestamp: time.Now(),
15        }
16    },
17    func(cached any) bool {
18        // Validate that the cached value is not older than 1 hour
19        if tv, ok := cached.(TimestampedValue); ok {
20            return time.Since(tv.Timestamp) < time.Hour
21        }
22        return false
23    },
24)

Functions 1

func New

1func New() *Memoizer
source

New creates a new Memoizer instance.

Types 1

type Memoizer

struct
1type Memoizer struct {
2	cache *bptree.BPTree
3}
source

Memoizer is a structure to handle memoization of function results.

Methods on Memoizer

func Clear

method on Memoizer
1func (m *Memoizer) Clear()
source

Clear clears all cached values.

func Invalidate

method on Memoizer
1func (m *Memoizer) Invalidate(key any)
source

Invalidate removes the cached value for the specified key.

func Memoize

method on Memoizer
1func (m *Memoizer) Memoize(key any, fn func() any) any
source

Memoize ensures the result of the given function is cached for the specified key.

func MemoizeWithValidator

method on Memoizer
1func (m *Memoizer) MemoizeWithValidator(key any, fn func() any, isValid func(any) bool) any
source

MemoizeWithValidator ensures the result is cached and valid according to the validator function.

func Size

method on Memoizer
1func (m *Memoizer) Size() int
source

Size returns the number of items currently in the cache.

Imports 2

Source Files 3