I'm using slow data loading and calculations and would like to cache the results, so next time it would be faster.
Example - we would like to have two functions 1) convert currency to USD and 2) calculate CPI-index (Consumer Price Index).
echo to_usd("EUR", (2000, 1, 1), false) # => 0.846
echo to_cpi("USD", (2000, 1, 1)) # => 144.0
I wonder if it would be possible to auto-generate the caching code, maybe use some library? Something like:
proc to_usd_slow*(currency: string, time: TimeD): float =
1.0 # some slow calculations
proc to_usd* = cache(to_usd_slow)
I'm currently write cache manually, as in the code below, playground:
import hashes, tables
proc autohash*[T: tuple|object](o: T): Hash =
for f in o.fields: result = result !& f.hash
type
TimeD = tuple[year, month, day: int]
PointM = tuple[time: TimeD, value: float]
# CPI - Consumer Price Index
proc to_cpi_slow(currency: string, time: TimeD, extrapolate: bool): float =
1.0 # some slow calculations
# Cached version ---------------------------------------------------------------
type ToCpiKey = (string, TimeD, bool)
proc hash(v: ToCpiKey): Hash = v.autohash
var to_cpi_cache = init_table[ToCpiKey, float]()
proc to_cpi*(currency: string, time: TimeD, extrapolate: bool): float =
let key: ToCpiKey = (currency, time, extrapolate)
if key notin to_cpi_cache:
to_cpi_cache[key] = to_cpi_slow(currency, time, extrapolate)
to_cpi_cache[key]
# Curency conversions ----------------------------------------------------------
proc to_usd_slow*(currency: string, time: TimeD): float =
1.0 # some slow calculations
type ToUsdMKey = (string, TimeD)
proc hash(v: ToUsdMKey): Hash = v.autohash
var to_usd_cache = init_table[ToUsdMKey, float]()
proc to_usd*(currency: string, time: TimeD): float =
let key: ToUsdMKey = (currency, time)
if not(key in to_usd_cache): to_usd_cache[key] = to_usd_slow(currency, time)
to_usd_cache[key]
# Usage ------------------------------------------------------------------------
echo to_cpi("USD", (2000, 1, 1), false)
echo to_usd("EUR", (2000, 1, 1))