2010-12-06 11 views
7

descargo de responsabilidad: este código es una mala práctica., y solo funciona debido a algo parecido a un error. Nunca lo use en una situación real. Esta pregunta es sobre el comportamiento interesante de R, nada más que eso.Comportamiento de R con ifelse y eval en combinación

Después de leer this question Me quedé bastante perplejo. Aparentemente, ifelse puede acceder a información que debe estar oculta.

decimos que:

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

> eval(x) 
> eval(y) 
> 

Obtenemos sin salida. Lógica, ya que ambas expresiones son realmente asignaciones de un vector dd. eval() no debe dar salida entonces. Pero, por extraño que parezca, cuando intenta el código divertido

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

¿Obtiene salida ??? Alguien tiene una explicación para esto?

No es tan simple como "R evalúa y luego usa dd". Sea cual sea el orden que le dé a z, cualquiera que sea la condición que use, dd es siempre el último eval() mencionado.

> 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:

un vistazo más de cerca el código fuente de ifelse muestra que la línea de hacer que esto suceda, es el rep():

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

embargo, que doesn' t resolver la pregunta ...

+1

* PROBABLEMENTE * eval devuelve el objeto invisible. – kohske

+0

@koshke: parece que sí. str (eval (x)) da el objeto. Ponlo como una respuesta y lo aceptaré. –

Respuesta

5

Esto no es un error

La 'salida' en la consola del resultado de un comando es condicional. Esto puede ser determinado por la función en sí - por ejemplo:

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

El valor todavía se está volviendo muy bien - sólo que no está impreso en la consola.

lo que está sucediendo aquí es el eval marca su salida invisible pero rep y ifelse no lo hacen, y de hecho la tira con eficacia la propiedad invisible fuera de su entrada.

Parece que lo invisible es una propiedad especial de la variable y no se pasa a través de la operación de rep. Tampoco es pasar a través de la asignación:

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

Ver ?invisible por un poco más de fondo.

+0

muy bien. También para los ejemplos, aparentemente malinterpreté completamente la función 'eval()'. –

2

R siempre evalúa las dos alternativas a un comando ifelse. Puede racionalizar eso como necesario para estar listo para elegir qué elemento en cada vector para volver al entorno de llamada. Lo contrario es cierto de un if (cond) {affirm-conseq} else {neg-conseq}. La base de "dd" siempre se establece sobre la base de la evaluación del tercer argumento ifelse cuando se ve el código ifelse.El código de "no" -vector se evalúa después del vector "sí" para elegir qué elementos del vector consecutivo negativo se asignan al vector de salida "ans".

+0

eso fue lo más lejos que conseguí. Me echaba de menos que eval() siempre devuelve un objeto, aunque sea un objeto invisible. –

Cuestiones relacionadas