Skip to content

Instantly share code, notes, and snippets.

@jayrhynas
Last active July 21, 2025 15:12
Show Gist options
  • Save jayrhynas/fd11e61ba9c0dd4ab046240fa9cfcd09 to your computer and use it in GitHub Desktop.
Save jayrhynas/fd11e61ba9c0dd4ab046240fa9cfcd09 to your computer and use it in GitHub Desktop.
struct Memoize<each Arg: Hashable, R> {
typealias Generator = (repeat each Arg) -> R
private let generator: Generator
init(_ generator: @escaping Generator) {
self.generator = generator
}
private typealias Key = [AnyHashable]
private func makeKey(_ args: repeat each Arg) -> Key {
var key: [AnyHashable] = []
for arg in repeat each args {
key.append(AnyHashable(arg))
}
return key
}
private class Cache {
var storage: [Key: R] = [:]
}
private let cache = Cache()
private func computeAndCache(key: Key, _ args: repeat each Arg) -> R {
let result = generator(repeat each args)
cache.storage[key] = result
return result
}
func recompute(_ args: repeat each Arg) -> R {
computeAndCache(key: makeKey(repeat each args), repeat each args)
}
@discardableResult
func removeValue(for args: repeat each Arg) -> R? {
cache.storage.removeValue(forKey: makeKey(repeat each args))
}
func callAsFunction(_ args: repeat each Arg) -> R {
let key = makeKey(repeat each args)
return cache.storage[key] ?? computeAndCache(key: key, repeat each args)
}
}
class Tester {
func _calculate(a: Int, b: Int, c: Int) -> Int {
defer { print("calculated with \(a), \(b), \(c)")}
return a * a + b * b + c * c
}
private(set) lazy var calculate = Memoize(_calculate)
func main() {
print(calculate(2, 4, 6)) // calculated with 2, 4, 6
// 56
print(calculate(2, 4, 8)) // calculated with 2, 4, 8
// 84
print(calculate(2, 4, 6)) // 56
print(calculate(2, 4, 8)) // 84
calculate.removeValue(for: 2, 4, 6)
print(calculate(2, 4, 6)) // calculated with 2, 4, 6
// 56
print(calculate(2, 4, 8)) // 84
}
}
Tester().main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment