отладить функцию, когда был использован Safely from Purrr? - PullRequest
3 голосов
/ 17 апреля 2020

У меня есть функция, которая была сохранена как объект Rds, и мне интересно, есть ли возможность после чтения функции для debug() ее или для просмотра кода внутри функции?

Пример

library(purrr)

some_function <- function(x){


  avg <- mean(x)
  std <- sd(x)

  return(c(avg, std))

} 

safe_function <- safely(some_function)

saveRDS(safe_function, 'safe_function.rds')
rm(safe_function)

# How can I debug the function or make changes to it after I've loaded it?

safe_function <- readRDS('safe_function.rds')

Ответы [ 2 ]

3 голосов
/ 21 апреля 2020

Короткий ответ заключается в том, что легко извлечь базовую функцию с помощью одной строки кода:

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), поэтому его легко изменить, если необходимо.

3 голосов
/ 21 апреля 2020

Вот один из способов сделать это:

  1. Выполнить debug(safe_function) в консоли и затем вызвать вашу функцию, скажем, safe_function(c(1, 2))
  2. В это время вы будете в режиме отладки: enter image description here
  3. В консоли выполните команду debugonce(.f), а затем нажмите «Далее» или «Продолжить» (в качестве альтернативы введите n или c в консоль)
  4. Теперь вы будете в теле вашего some_function и сможете увидеть код: enter image description here
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...