Короткий ответ заключается в том, что легко извлечь базовую функцию с помощью одной строки кода:
extracted_function <- environment(safe_function)$.f
extracted_function
#> function(x){
#>
#>
#> avg <- mean(x)
#> std <- sd(x)
#>
#> return(c(avg, std))
#>
#> }
#> <bytecode: 0x1951c3e0>
Вы можете отлаживать эту функцию так, как вам нравится, тогда, если вы хотите перезаписать ее, но сохранить в оболочке safely
вы можете перезаписать ее следующим образом:
debugged_function <- function(x) c(mean(x, na.rm = TRUE), sd(x, na.rm = TRUE))
environment(safe_function)$.f <- debugged_function
safe_function(1:10)
#> $result
#> [1] 5.50000 3.02765
#>
#> $error
#> NULL
Я кратко объясню, почему это работает:
Если вы изучите свой safe_function
, вы заметите пару необычных вещей об этом. Хотя вы загрузили его в глобальную среду, он фактически обернут в свою собственную неназванную среду (в данном случае <environment: 0x095704c0>
), которая является неотъемлемой частью его работы:
safe_function
#> function (...)
#> capture_error(.f(...), otherwise, quiet)
#> <bytecode: 0x0956fd50>
#> <environment: 0x095704c0>
Другое странное вы заметите, что safe_function
вызывает функцию .f
, которая не является ни встроенной функцией, ни функцией, экспортированной из purrr
. Это потому, что .f
является копией вашей исходной функции, которая хранится в этой специальной среде.
Мы можем посмотреть полное содержимое безымянной среды, выполнив:
ls(environment(safe_function), all.names = TRUE)
#> [1] ".f" "otherwise" "quiet"
Теперь Если вы посмотрите, что такое .f
, вы обнаружите, что это просто копия вашего оригинала some_function
:
#> function(x){
#>
#>
#> avg <- mean(x)
#> std <- sd(x)
#>
#> return(c(avg, std))
#>
#> }
#> <bytecode: 0x1951c3e0>
Так что именно здесь ваша скрытая функция «скрывается». Он остается доступным как участник этой безымянной среды, к которой можно получить доступ через environment(safe_function)
, поэтому его легко изменить, если необходимо.