Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R's behaviour using ifelse and eval in combination

disclaimer: this code is bad practice., and only works due to something bug-like. Never use it in a real situation. This question is about the interesting behaviour of R, nothing else than that.

After reading this question I got pretty puzzled. Apparently, ifelse can access information that should be hidden.

Say we do :

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

> eval(x)
> eval(y)
>

We get no output. Logic, as both expressions are actually assignments of a vector dd. eval() is not supposed to give output then. But strangely enough, when you try the funny code

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

You get output??? Somebody has an explanation for this?

It's not as simple as "R evaluates and then uses dd". Whatever order you give z, whatever condition you use, dd is always the last mentioned 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

EDIT:

a closer look at the source code of ifelse shows that the line making sure this happens, is the rep() :

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

Still, it doesn't solve the question...

like image 417
Joris Meys Avatar asked Dec 06 '10 12:12

Joris Meys


1 Answers

This is not a bug

The 'output' onto the console of the result of a command is conditional. This can be determined by the function itself - for example:

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

The value is still being returned just fine - it's just not printed on the console.

What's happening here is the eval marks its output invisible but rep and ifelse do not, and in fact effectively strip the invisible property off their input.

It appears the invisible is a special property of the variable, and is not passed through the rep operation. It's also not passed through assignment:

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

See ?invisible for a little more background.

like image 114
Alex Brown Avatar answered Oct 04 '22 13:10

Alex Brown