Что такое локальная / глобальная проблема с R? - PullRequest
0 голосов
/ 14 июля 2011

При каких обстоятельствах следующий пример возвращает локальный x по сравнению с глобальным x?

В блоге xi'an было написано следующее в http://xianblog.wordpress.com/2010/09/13/simply-start-over-and-build-something-better/

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

f =function() {
if (runif(1) > .5)
x = 10
x
}

Х, возвращаемый этой функцией, является случайным локальным или глобальным.Есть и другие примеры, где переменные чередуются между локальными и нелокальными по всему телу функции.Никакой разумный язык не позволил бы этого.Это уродливо и делает оптимизацию действительно трудной.Это не единственная проблема, даже более странные вещи происходят из-за взаимодействия между областью видимости и ленивой оценкой.

PS - Это сообщение в блоге Сианя написано Россом Ихакой?

Редактировать - Подписатьсяна вопрос.

Это лекарство?

f = function() {
  x = NA
  if (runif(1) > .5)
    x = 10
  x
}

Ответы [ 2 ]

6 голосов
/ 14 июля 2011

Это проблема, только если вы пишете функции, которые не принимают аргументов, или функциональность зависит от области видимости переменных вне текущего фрейма. вы либо i) передаете нужные объекты в функцию в качестве аргументов этой функции, либо ii) создаете эти объекты внутри функции, которая их использует.

Ваш f закодирован неправильно. Если вы, возможно, изменили x, то вы должны передать x, возможно установив значение по умолчанию NA или подобное, если вы хотите, чтобы другая сторона случайного броска была.

f <- function(x = NA) {
    if (runif(1) > .5)
    x <- 10
    x
}

Здесь мы видим, что функция работает в соответствии с вашей второй функцией, но при правильном назначении x в качестве аргумента с соответствующим значением по умолчанию. Обратите внимание, что это работает, даже если у нас есть еще один x, определенный в глобальном рабочем пространстве:

> set.seed(3)
> replicate(10, f())
 [1] NA 10 NA NA 10 10 NA NA 10 10
> x <- 4
> set.seed(3)
> replicate(10, f())
 [1] NA 10 NA NA 10 10 NA NA 10 10

Еще одним преимуществом этого является то, что вы можете передать x, если вы хотите вернуть другое значение вместо NA. Если вам не нужна эта возможность, тогда достаточно указать x <- NA в , и функция будет достаточной.

Вышесказанное основано на том, что вы действительно хотите сделать с f, что не ясно из ваших сообщений и комментариев. Если все, что вы хотите сделать, это случайно вернуть 10 или NA, определите x <- NA.

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

f <- function(n = 1, repl = 10) {
    out <- rep(NA, n)
    out[runif(n) > 0.5] <- repl
    out
}

или

f <- function(x, repl = 10) {
    n <- length(x)
    out <- rep(NA, n)
    out[runif(n) > 0.5] <- repl
    out
}

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

1 голос
/ 14 июля 2011

'x' объявляется в функции только в том случае, если условие 'if' истинно, поэтому, если 'runif (1)>. 5', то второе упоминание о x заставит функцию вернуть ваш локальный x (10). ), в противном случае он вернет глобально определенный «x» (а если «x» не определен глобально, то произойдет сбой)

    > f =function() {
    + if (T)
    + x = 10
    + x
    + }
    > f()
    [1] 10

    > f =function() {
    + if (F)
    + x = 10
    + x
    + }
    > f()
    Error in f() : Object 'x' not found

    > x<-77
    > f()
    [1] 77
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...