Функции R, которые выполняют функции

Я пытаюсь разбить общие строки кода, используемые в довольно большом R-скрипте, на инкапсулированные функции... однако они, похоже, не запускают предполагаемый код при вызове. Я чувствую, что мне не хватает какой-то концептуальной части того, как работает R или функциональное программирование в целом.

Примеры:

Вот фрагмент кода, который я хотел бы вызвать, чтобы очистить рабочее пространство:

clearWorkSpace <- function() {
  rm(list= ls(all=TRUE))
}

Как уже отмечалось, код внутри функции выполняется, как и ожидалось, однако при вызове родительской функции среда не очищается.

Опять же, вот функция, предназначенная для загрузки всех файлов зависимостей -

loadDependencies <- function() {
  dep_files <- list.files(path="./dependencies")
  for (file in dep_files) {
    file_path <- paste0("./dependencies/",file)
    source(file_path,local=TRUE)
  }
}

Если возможно, было бы здорово иметь возможность инкапсулировать код в легко читаемые функции. Заранее благодарны за Вашу помощь.


person huxfurpaw    schedule 08.11.2016    source источник


Ответы (2)


То, что вы называете рабочей областью, правильнее называть глобальной средой.

Функции выполняются в собственной среде. Вот, например, почему вы не видите переменные, определенные внутри функции в вашей глобальной среде. Кроме того, как функция знает, что нужно использовать переменную с именем x, определенную в теле функции, а не какую-то x, которая может оказаться в вашей глобальной среде.

Большинство функций не изменяют внешнюю среду, и это хорошо! Это парадигма функционального программирования. Функции, которые изменяют среду, например rm и source, обычно принимают аргументы, чтобы вы могли явно указать, какая среда изменяется. Если вы посмотрите на ?rm, вы увидите аргумент envir, и этот аргумент представляет собой большую часть того, что описывает его раздел Подробности. source имеет аргумент local:

local - TRUE, FALSE или среда, определяющая, где оцениваются проанализированные выражения. FALSE (по умолчанию) соответствует рабочей области пользователя (глобальной среде), а TRUE — среде, из которой вызывается source.

Вы явно устанавливаете local = TRUE при вызове source, который явно указывает source изменять только локальную (внутри функции) среду, поэтому, конечно, ваша глобальная среда не затрагивается!


Чтобы ваши функции работали так, как вы, как я предполагаю, хотите, вы можете изменить clearWorkSpace следующим образом:

clearWorkSpace <- function() {
  rm(list= ls(all=TRUE, envir = .GlobalEnv), envir = .GlobalEnv)
}

А для loadDependencies просто удалите local = TRUE. (Или более явно установить local = FALSE или local = .GlobalEnv) Хотя вы можете переписать его более R-подобным способом:

loadDependencies = function() {
    invisible(lapply(list.files(path = "./dependencies", full.names = TRUE), source))
}

Для обоих из них (особенно с упрощенной зависимостью, работающей выше) я бы задал вопрос, действительно ли вам нужны эти функции. Может быть, лучше просто взять за привычку перезапускать R, когда вы возобновляете работу над проектом, и держать invisible(lapply(list.files(path = "./dependencies", full.names = TRUE), source)) в верхней части вашего скрипта...


Дополнительную информацию о средах можно найти в разделе Advanced R, посвященном средам. Примечательно, что существует несколько способов указать среды, которые могут быть полезны для различных вариантов использования, а не жестко кодировать глобальную среду.

person Gregor Thomas    schedule 08.11.2016

Теоретически вам нужно просто сделать что-то вроде:

 rm(list= ls(all=TRUE, envir = .GlobalEnv))

Я имею в виду, что вы явно задаете среду (здесь даже лучше использовать аргумент pos). но это также удалит функцию clearWorkSpace, поскольку она определена в глобальной среде. Так что это не удастся с рекурсивным вызовом.

Лично я никогда не использую rm внутри функции или локального вызова. Насколько я понимаю, rm предназначен для вызова из консоли для очистки рабочей области.

person agstudy    schedule 08.11.2016