programacion perezosa lazy funcional evaluacion r lazy-evaluation assign

lazy - Evaluación perezosa en R-¿se ve afectada la asignación?



lazy programacion (1)

El lenguaje R generalmente tiene valor semántico . La asignación x <- y significa que x e y serán copias independientes del mismo objeto (las actualizaciones en y y x serán independientes). Una implementación ingenua de x <- y siempre asignaría memoria para x y copiaría completamente y en ella. GNU-R en su lugar utiliza un mecanismo de copia en escritura, pospondría la copia hasta que realmente ocurra una actualización, lo que ahorra tiempo de memoria / ejecución en caso de que no ocurra. Los usuarios R no tienen que saber acerca de esta optimización, es totalmente transparente (excepto en algunos casos raros como errores de memoria insuficiente). Este mecanismo se aplica a la asignación escrita como x <- y y assign("x", y) igual.

La evaluación perezosa es parte del diseño del lenguaje y es visible para los usuarios / programadores de R. Las expresiones pasadas como argumentos a una función, por ejemplo, en foo(ls()) la expresión pasada es ls() , se evalúan perezosamente, solo si y cuando sea necesario, mediante la implementación de la función llamada.

delayedAssign es una función de bajo nivel, visible para usuarios / programadores de R, pero en realidad solo se utiliza para la carga lenta de paquetes y no debería ser necesaria en los programas de usuario. delayedAssign permite especificar una expresión para calcular el valor de una variable; el cálculo se realizará de forma perezosa solo si / cuando se lee la variable la primera vez.

Por lo tanto, para responder a la pregunta, una asignación en R siempre es '''' perezosa '''' en el sentido de que se utiliza el mecanismo de copia en escritura. El cálculo del lado derecho de la asignación también puede ser lento (utilizando delayedAssign ), pero eso no debería ser necesario / utilizado por los programas del usuario.

Creo que para el '''' cambio de nombre '''' de las variables, no hay necesidad de usar delayedAssign (porque el lado derecho no está computado). Solo hace que la situación sea más compleja y es probable que haya una sobrecarga de rendimiento debido a la delayedAssign contabilidad que tiene que hacer delayedAssign . Solo usaría la asignación ordinaria si tuviera que cambiar el nombre de las variables.

Para mayor claridad del código, siempre que sea posible, trataré de evitar eliminar las variables de los entornos e incluso asignarlas de una función al entorno global, por ejemplo, crearía una nueva lista e insertaría los nuevos enlaces (variables) en ella.

Habiendo mencionado el mecanismo de copia en escritura, con la implementación actual en GNU-R, cualquiera de las soluciones descritas causará potencialmente una copia de memoria que no sería necesaria si las variables no hubieran sido renombradas. No hay forma de evitar esto en el nivel R

Leí esta pregunta básica sobre el cambio de nombre de los objetos y la respuesta de @Shane, indicándome una evaluación perezosa. Ahora me pregunto si assign es evaluado perezosamente, también. Al igual que aquí:

assign("someNewName",someOldObject) rm(someOldObject)

La razón por la que me pregunto sobre esto es el siguiente caso de uso: Supongamos que tengo 10K + R objetos, cada uno de los cuales tiene dos atributos llamados nombre originalName y nombre additionalName . Ahora quiero escribir una función que permita al usuario cambiar de un nombre a otro de manera eficiente sin perder estos dos atributos. Aproximadamente como esto ...

EDIT: basado en la entrada de @ Hadley, he cambiado mi código.

switchObjectName <- function(x) { n1 <- attributes(x)$originalName n2 <- attributes(x)$additionalName objName <- deparse(substitute(x)) if(objName == n1) { delayedAssign(n2,x,assign.env=.GlobalEnv) } else { delayedAssign(n1,x,assign.env=.GlobalEnv) } rm(list=c(objName),envir=.GlobalEnv) }

esto funciona bien, pero tuve algunos problemas para hacer la declaración correcta. Intenté rm(objName,envir=.GlobalEnv) pero no pude hacerlo funcionar aunque objName es definitivamente un carácter porque es el resultado de deparse(substitute(x) .