Необходимо проверить функцию мемоизированного пакета, чтобы мемоизация работала
Допустим, у меня есть пакет со следующей функцией:
foo <- function() {
Sys.sleep(1) # really expensive operation
return(1)
}
Значение функции всегда одно и то же для каждого прогона, поэтому я хотел бы использовать мемоизацию.
Я думал, что могу просто сделать
foo <- memoise::memoise(function() {
Sys.sleep(1) # really expensive operation
return(1)
})
Однако это не работает.
Я имею в виду, если запустить его как функцию GlobalEnv, он работает:
foo <- memoise::memoise(function() {
Sys.sleep(1)
return(1)
})
system.time(foo())
#> user system elapsed
#> 0 0 1
system.time(foo())
#> user system elapsed
#> 0.01 0.00 0.01
Создано 23.12.2019 пакетом REPEX (v0.3.0)
Однако, если он находится в пакете, я получаю действительно странное поведение. В общем, запоминание не срабатывает, и я продолжаю получать ту же цену. Однако, если я распечатаю определение функции, оно начнет работать!
system.time(bar::foo())
#> user system elapsed
#> 0.47 0.08 2.55
system.time(bar::foo())
#> user system elapsed
#> 0 0 2
system.time(bar::foo())
#> user system elapsed
#> 0.02 0.00 2.02
system.time(bar::foo())
#> user system elapsed
#> 0.01 0.00 2.02
bar::foo
#> Memoised Function:
#> function() {
#> Sys.sleep(2)
#> return (1)
#> }
#> <environment: namespace:bar>
system.time(bar::foo())
#> user system elapsed
#> 0 0 2
system.time(bar::foo())
#> user system elapsed
#> 0 0 0
system.time(bar::foo())
#> user system elapsed
#> 0 0 0
system.time(bar::foo())
#> user system elapsed
#> 0 0 0
Для протокола, вот соответствующие части NAMESPACE
а также DESCRIPTION
файлы:
# NAMESPACE
export(foo)
importFrom(memoise,memoise)
# DESCRIPTION [...]
Imports:
memoise
Что здесь происходит и что мне делать, чтобы мемоизация работала с самого начала в моем пакете?
1 ответ
Похоже на ошибку в memoise
пакет. Когда вы работаете над своим собственным пакетом, R может добавлять отладочную информацию (называемуюsrcref
s) к функциям. Что-то в этом приводит к тому, что хэш выводится по-разному каждый раз, когда вы вызываете функцию, поэтому он никогда не распознает, что вы вызываете с одними и теми же аргументами.
Простым обходным решением является удаление параметра установки "--with-keep.source" при установке собственного пакета. (Если вы используете RStudio, это добавляется автоматически вProject Options | Build Tools | Install and Restart...
.) Это остановит R от добавления srcref
, и ошибка в memoise
не сработает. К сожалению, это наносит вред отладчику в RStudio и других интерфейсах, поэтому он не идеален.
Другой обходной путь, который не мешает работе отладчика (за исключением этой функции), - использовать removeSource
на цель, которая запоминается. Например,
foo <- memoise::memoise(removeSource(function() {
Sys.sleep(1) # really expensive operation
return(1)
}))