You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否对嵌套函数使用memoise?R语言代码场景咨询

关于memoise在purrr::map矢量化函数中的最佳实践问题

我按照建议用purrr::map而非Vectorize实现了矢量化的数据加载函数,代码结构如下:

load_data <- function(key){
  load_data_one <- function(key){
    ...
    # 根据key获取数据的逻辑
    ...
    data
  }
  # 支持传入key向量,返回合并后的结果
  result <- map_dfr(key, load_data_one) 
}

由于数据检索成本很高,我想了解memoise包在此场景下的最佳使用方式,具体疑问如下:

  • 理想方案是给嵌套的load_data_one加缓存,这样调用load_data处理向量时只会计算未缓存过的key,这个思路是否正确?
  • 如果转而给load_data加缓存,当传入的key向量和之前略有不同时,memoise能不能只计算新增的元素?
  • 给嵌套的load_data_one用memoise有没有潜在问题?是否需要把它移到load_data外面?

解答

1. 给嵌套的load_data_one加缓存是最优选择

这个思路完全正确。因为load_data_one是针对单个key的逻辑,给它加memoise后,每次调用load_data处理向量时,每个key都会先检查缓存:如果之前已经加载过这个key的数据,直接从缓存取;只有未缓存的key才会执行实际的检索逻辑,能最大化减少重复的高成本检索,完美匹配你“仅计算未知结果”的需求。

2. 给load_data加缓存无法实现“仅计算新元素”

memoise是基于整个函数的输入参数来缓存结果的。如果两次传入的key向量哪怕只有一个元素不同,memoise都会认为是全新的输入,会重新执行整个load_data函数——也就是重新遍历所有key并执行检索,完全不会复用之前缓存过的单个key的结果。这种方式缓存粒度太粗,达不到你想要的效果,不推荐。

3. 嵌套的load_data_one使用memoise的潜在问题与解决

直接在load_data内部给load_data_one加memoise会有缓存失效的问题:每次调用load_data时,都会重新定义load_data_one这个函数,而memoise是绑定在函数对象上的。这意味着每次调用load_data,load_data_one都是一个新的函数实例,之前的缓存会丢失,相当于每次都要重新缓存所有key,完全起不到复用的作用。

解决方法很简单:把load_data_one移到load_data外部,然后给它加memoise。修改后的代码结构如下:

# 先定义单个key的加载函数并缓存
load_data_one <- memoise::memoise(function(key){
  ...
  # 根据key获取数据的逻辑
  ...
  data
})

# 矢量化的入口函数
load_data <- function(key){
  result <- purrr::map_dfr(key, load_data_one) 
}

这样load_data_one是一个全局的函数实例,memoise的缓存会一直保留,每次调用load_data时都能复用之前的缓存结果。


内容的提问来源于stack exchange,提问作者Hauke L.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 06:30:53