Ограничение диапазона переменных

Я пытаюсь написать функцию, которая ограничивает область переменных R. Например,

source("LimitScope.R")
y = 0
f = function(){
   #Raises an error as y is a global variable
   x = y
}

Я думал о тестировании переменной среды, но не был уверен в том, как это сделать.

Почему

Я учу R для подражания. В их первых двух практиках некоторые из них всегда забывают о переменном объеме, поэтому их поданные функции не работают. Например, я всегда получаю что-то вроде:

n = 10
f = function(x){
  #Raises an error
  #as I just source f and test it for a few test cases.
  return(x*n)
}

Я был после быстрой функции, которая бы "отключила" область. Как вы можете себе представить, это не должно быть особенно надежным, поскольку это можно было бы предложить только для нескольких практик.

Ответ 1

Я не уверен, что вы хотите сделать это в целом, но функция local() должна помочь, как и библиотека codetools.

В вашем примере попробуйте

f = local( function() { ... }, baseenv())

Он не делает именно то, что вы хотите, но он должен приблизить вас.

Ответ 2

Вы можете заставить переменную локальную версию с этой функцией:

get_local <- function(variable)
{
  get(variable, envir = parent.frame(), inherits = FALSE)  
}

Сравните эти случаи

y <- 0    
f <- function()
{
  x <- y
}    
print(f())        # 0

y <- 0    
f <- function()
{
  y <- get_local("y")
  x <- y
}    
print(f())        # Error: 'y' not found

В зависимости от того, что вы делаете, вы также можете проверить, был ли y аргументом f, используя formalArgs или formals.

g  <- function(x, y = TRUE, z = c("foo", "bar"), ...) 0

formalArgs(g)
# [1] "x"   "y"   "z"   "..."

formals(g)
#$x
#
#
#$y
#[1] TRUE
#
#$z
#c("foo", "bar")
#
#$...

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

Ответ 3

Вы можете проверить, существует ли y в глобальной среде, используя exists('y',envir=.GlobalEnv)

Ответ 4

Что случается со мной, так это то, что у меня есть разделенный экран в ESS с файловым буфером R-кода слева и интерпретатором справа. Возможно, я установил некоторые значения в интерпретаторе, пока я отлаживаю код, над которым я работаю в буфере. Тогда возможно, что код в буфере случайно ссылается на то, что я установил в intrereter. Это трудно обнаружить, если я не буду оценивать свой буфер в новом интерпретаторе каждый раз, что не работает по умолчанию ESS.

Если это та проблема, которую вы часто видите, rm (list = ls (envir =.GlobalEnv)) в том, что вам может помочь источник, но это, конечно, создает другие проблемы, такие как стирание всего, что было использование для сохранения состояния при отладке и т.д.