Поведение R с использованием ifelse и eval в комбинации - PullRequest
7 голосов
/ 06 декабря 2010

отказ от ответственности: этот код является плохой практикой. и работает только из-за ошибки, подобной . Никогда не используйте его в реальной ситуации.Этот вопрос об интересном поведении R, ничего кроме этого.

После прочтения этого вопроса я довольно озадачен.Очевидно, ifelse может получить доступ к информации, которая должна быть скрыта.

Скажем, мы делаем:

> x <- expression(dd <- 1:3)    
> y <- expression(dd <- 4:6)    
> z <- c(1,0)

> eval(x)
> eval(y)
>

Мы не получаем вывод.Логика, так как оба выражения на самом деле являются присваиваниями вектора dd.Тогда eval () не должен выдавать вывод.Но как ни странно, когда вы пытаетесь смешной код

> ifelse(z==0,eval(x),eval(y))
[1] 4 2

Вы получаете вывод ???У кого-нибудь есть объяснение этому?

Это не так просто, как «R оценивает, а затем использует dd».Независимо от того, какой порядок вы даете z, какое бы условие вы ни использовали, dd всегда является последним упомянутым eval().

> ifelse(z==0,eval(x),eval(y))
> dd
[1] 4 5 6

> ifelse(z==1,eval(x),eval(y))
> dd
[1] 4 5 6

> z <- c(0,1)
> ifelse(z==0,eval(x),eval(y))
> dd
[1] 4 5 6

> ifelse(z==1,eval(x),eval(y))
> dd
[1] 4 5 6

> ifelse(z==1,eval(y),eval(x))
> dd
[1] 1 2 3

РЕДАКТИРОВАТЬ:

. Более подробный анализ исходного кода ifelseпоказывает, что строка, обеспечивающая это, является rep():

> x <- expression(dd <- 1:3)
> eval(x)
> rep(eval(x),2)
[1] 1 2 3 1 2 3

Тем не менее, это не решает вопрос ...

Ответы [ 2 ]

5 голосов
/ 06 декабря 2010

Это не ошибка

Вывод на консоль результата команды является условным. Это может быть определено самой функцией - например:

> f=function(x)x;
> g=function(x)invisible(x);
> f(1)
[1] 1
> g(2)
> .Last.value
[1] 2

Значение по-прежнему возвращается просто отлично - оно просто не печатается на консоли.

Здесь происходит то, что eval помечает свой вывод invisible, а rep и ifelse - нет, и фактически фактически удаляет свойство invisible со своего ввода.

Похоже, что невидимое является специальным свойством переменной и не передается через операцию rep. Это также не передается через назначение:

> h=function(x){y=x;y;}
> f(g(1))
> h(g(1))
[1] 1
>

См. ?invisible для дополнительной информации.

2 голосов
/ 06 декабря 2010

R всегда оценивает две альтернативы команде ifelse.Вы можете рационализировать это как необходимое для того, чтобы быть готовым выбрать, какой элемент в каждом векторе возвращать в вызывающую среду.Противоположное верно для if (cond) {affirm-conseq} else {neg-conseq}.Основа «dd» всегда устанавливается на основе оценки третьего аргумента ifelse, когда он смотрит на код для ifelse.Код «no» -vector вычисляется после вектора «yes», чтобы выбрать, какие элементы в отрицательном последовательном векторе будут назначены вектору «ans» -output.

...