Add "memoized"

This commit is contained in:
2026-01-25 13:58:27 +01:00
parent 08bd59f118
commit 9cc7a41b08

42
main.go
View File

@@ -8,6 +8,7 @@ import (
"net/http"
"os"
"path/filepath"
"reflect"
"sync"
"golang.org/x/time/rate"
@@ -217,3 +218,44 @@ func RequestCached[T any](req *http.Request, filename string) (T, error) {
func RequestCachedBytes(req *http.Request, filename string) ([]byte, error) {
return RequestCached[[]byte](req, filename)
}
// Memoized creates a memoized version of the provided function using reflection.
// The returned function caches results based on the string representation of arguments,
// returning cached results for repeated calls with the same arguments.
//
// Parameters:
// - fn: The function to memoize (must be a function type)
//
// Returns a memoized version of the function with the same signature.
//
// Example:
//
// func expensive(a string, b int) (string, error) {
// fmt.Println("Computing...")
// return fmt.Sprintf("Result: %s, %d", a, b), nil
// }
//
// memoized := Memoized(expensive).(func(string, int) (string, error))
// result, _ := memoized("hello", 42) // Computes
// result, _ = memoized("hello", 42) // Returns cached result
//
// Note: The cache key is generated using fmt.Sprintf("%v", args), which may not
// uniquely identify all argument combinations. This function is not thread-safe.
func Memoized(fn interface{}) interface{} {
fnVal := reflect.ValueOf(fn)
fnType := fnVal.Type()
cache := make(map[string][]reflect.Value)
return reflect.MakeFunc(fnType, func(args []reflect.Value) []reflect.Value {
key := fmt.Sprintf("%v", args)
if cached, ok := cache[key]; ok {
return cached
}
results := fnVal.Call(args)
cache[key] = results
return results
}).Interface()
}