varias superponer style studio modificar graficos graficas ejes div r list environment assign

superponer - tags$style shiny



AsignaciĆ³n para reemplazar valor en lista no local (1)

[[<- comporta de manera diferente para listas y entornos cuando se usa en objetos no locales:

lst = list() env = new.env() (function () lst[[''x'']] = 1)() (function () env[[''x'']] = 1)()

lst # list() as.list(env) # $x # [1] 1

En otras palabras, si el objetivo de [[<- es un entorno, modifica el entorno (no local), pero si es un vector / lista, crea un nuevo objeto local.

Me gustaría saber dos cosas:

  1. ¿Por qué esta diferencia de comportamiento?
  2. ¿Hay una manera de lograr el mismo resultado para las listas que para los entornos, sin utilizar <<- ?

Con respecto a (1) , soy consciente de las múltiples diferencias entre las listas y los entornos (en particular, sé que los entornos no se copian), pero la documentación no menciona por qué la semántica de [[<- difiere entre los dos - en En particular, por qué el operador operaría en diferentes ámbitos. ¿Es esto un error? Es contra-intuitivo al menos, y requiere algunos chanchullos de implementación no triviales. 1

Con respecto a (2) , la solución obvia es, por supuesto, utilizar <<- :

(function () lst[[''x'']] <<- 1)()

Sin embargo, prefiero entender la diferencia de manera rigurosa en lugar de simplemente trabajar con ellos. Además, he usado hasta ahora assign lugar de <<- y prefiero esto, ya que me permite un mayor control sobre el alcance de la tarea (en particular, ya que puedo especificar inherits = FALSE . <<- es demasiado vudú para mi gusto.

Sin embargo, lo anterior no se puede resolver (por lo que yo sé) mediante la assign porque la assign solo funciona en entornos, no en listas. En particular, si bien assign(''x'', 1, env) funciona (y hace lo mismo que arriba), assign(''x'', 1, lst) no funciona.

1 Para elaborar, por supuesto, se espera que R haga cosas diferentes para diferentes tipos de objetos utilizando el envío dinámico (por ejemplo, a través de S3). Sin embargo, este no es el caso aquí (al menos no directamente): la distinción en la resolución del alcance se produce antes de que se conozca el tipo de objeto del objetivo de la asignación; de lo contrario, lo anterior operaría en el primer lugar, en lugar de crear un nuevo objeto local. Entonces internamente [[<- tiene que hacer el equivalente de:

`[[<-` = function (x, i, value) { if (exists(x, mode = ''environment'', inherits = TRUE)) assign(i, value, pos = x, inherits = FALSE) else if (exists(x, inherits = FALSE) internal_assign(x, i, value) else assign(x, list(i = value), pos = parent.frame(), inherits = FALSE) }


La definición del lenguaje R (sección 2.1.10) dice:

A diferencia de la mayoría de los otros objetos R, los entornos no se copian cuando se pasan a funciones o se usan en asignaciones.

La sección "6.3 Más sobre la evaluación" también da una pista ligeramente relevante:

Tenga en cuenta que la evaluación en un entorno dado puede realmente cambiar ese entorno, más obviamente en los casos que involucran al operador de asignación, como

eval(quote(total <- 0), environment(robert$balance)) # rob Rob

Esto también es cierto cuando se evalúa en listas, pero la lista original no cambia porque uno realmente está trabajando en una copia.

Entonces, la respuesta a su primera pregunta es que las listas deben copiarse para asignarse a ellas, pero los entornos pueden modificarse en su lugar (lo que tiene enormes implicaciones de rendimiento).

Respecto a tu segunda pregunta:

Si está trabajando con una lista, la única opción parece ser

  • copiar la lista en el ámbito local (usando get ),
  • asignar a la lista,
  • utilice assign para copiar la lista modificada de nuevo en el entorno original.