Как добиться блокобзор в R? - PullRequest
0 голосов
/ 17 мая 2018

Я думаю о способах достижения блочной видимости в R. Это было бы неплохо для поддержания чистого рабочего пространства в тетрадях / интерактивных сессиях по науке о данных. На данный момент я использую шаблон IIFE , например,

(function(){
temp1 <- ...
temp2 <- ...
temp3 <- ...

data <<- fn(temp1, temp2, temp3)
})()

Таким образом, я могу создавать / обновлять данные и разрешать очистку временного после меня. Очевидно, что у него все еще есть побочные эффекты в отношении возможного присвоения глобальным, но для анализа данных, а не для пакетов программного обеспечения, я не обеспокоен.

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

`%gets%` <- function(x, val) {
    val <- local(val)
    assign(deparse(substitute(x)), val, envir = parent.frame())
}

x1 %gets% {
    x = 10;
    x + 5
}

Но x все еще выбрасывается в мою глобальную область видимости. Так

  1. Является ли это разумной реализацией для имитации видимости блока?
  2. Если это так, как я могу предотвратить выход моего x за пределы области видимости?

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

local делает то, что вы хотите (а IIFE - это хак в JavaScript, чтобы обойти отсутствие local -подобной функциональности).

Ваш код %gets% завершается ошибкой, потому что вы неправильно понимаете, как оцениваются аргументы: в вашей функции val является аргументом. Это означает, что оценивается в объеме вызывающего абонента , без исключений. Заключение в local просто означает, что результат оценки val заключен в локальный код, то есть в этом случае не имеет смысла. не означает, что выражение вычисляется локально; если бы это было так, вам бы не понадобился local, вы могли бы просто оценить его в области действия функции.

Вы можете сделать это, если хотите, используя eval:

`%gets%` = function (x, expr) {
    assign(
        as.character(substitute(x)),
        eval(substitute(expr)),
        parent.frame()
    )
}

... но это не будет очень полезно, так как он не может получить доступ к переменным области видимости вызывающего абонента; скорее, вам придется оценивать его в области, которая внедряет область действия вызывающего, чтобы у вас была «чистая» среда, но при этом вы могли получить доступ к существующим переменным:

`%gets%` = function (x, expr) {
    parent = parent.frame()
    assign(
        as.character(substitute(x)),
        eval.parent(substitute(eval(quote(expr), new.env(parent = parent)))),
        parent
    )
}

… но это, по сути, просто запутанный способ переопределения local назначения.

0 голосов
/ 17 мая 2018

1) локальный Первое замечание, что это работает:

if (exists("x")) rm(x) # just for reproducibility.  Don't need this normally.
x1 <- local({ x <- 10; x + 5})

x1
## [1] 15

x
## Error: object 'x' not found

2)% получает% Для реализации %gets% мы можем использовать substitute какэто:

`%gets%` <- function(.x, .value) {
  assign(deparse(substitute(.x)), eval.parent(substitute(local(.value))), parent.frame())
}

x1 %gets% {
    x = 10;
    x + 5
}

x1
## [1] 15

x
## Error: object 'x' not found

2a): = Мы можем сделать это еще лучше, определив: = вот так:

`:=` <- `%gets%`

# test
x1 := { x <- 10; x + 5}

x1
## [1] 15

x
## Error: object 'x' not found

3) трубы Также можно использовать трубопроводы, чтобы избежать глобальных изменений.Здесь x и y не сохраняются после завершения канала.

library(magrittr)

list(x = 6) %$% { y <- 1; x + y + 5 }
## [1] 12

x
## Error: object 'x' not found

y
## Error: object 'y' not found

или если нам нечего передать:

x1 <- list() %>% { x <- 10; x + 5 }

x1
## [1] 15

x
## Error: object 'x' not found

или мы можем использовать 0 для сохранения нажатий клавиш:

x1 <- 0 %>% { x <- 10; x + 5 }

Обновление Пересмотрены (2) для упрощения и исправления.Также добавлены (2a) и (3).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...