sesion - maildrop apple
¿Cómo se puede encontrar un método no importado en un paquete no adjunto mediante llamadas a funciones que no lo tienen en su espacio de nombres? (1)
No estoy seguro de si entiendo correctamente tu pregunta, pero el punto principal es que el group
es el vector de caracteres, mientras data$group
es un factor.
Después de adjuntar gmodels
, la llamada para reorder(factor)
llama a gdata:::reorder.factor
. así, reorder(factor(group))
llama.
En la transform
, la función se evalúa dentro del entorno del primer argumento, por lo que en T2 <- transform(data, group = reorder(group,-num))
, group
es factor.
ACTUALIZADO
library
adjunta los paquetes de importación al espacio de nombres cargado.
> loadedNamespaces()
[1] "RCurl" "base" "datasets" "devtools" "grDevices" "graphics" "methods"
[8] "stats" "tools" "utils"
> library(gmodels) # here, namespace:gdata is loaded
> loadedNamespaces()
[1] "MASS" "RCurl" "base" "datasets" "devtools" "gdata" "gmodels"
[8] "grDevices" "graphics" "gtools" "methods" "stats" "tools" "utils"
Por si acaso, la reorder
genérica existe en namespace:stats
:
> r <- ls(.__S3MethodsTable__., envir = asNamespace("stats"))
> r[grep("reorder", r)]
[1] "reorder" "reorder.default" "reorder.dendrogram"
Y para más detalles.
La llamada de reorder
buscará el S3generics en dos envs:
?UseMethod
primero en el entorno en el que se llama la función genérica, y luego en la base de datos de registro para el entorno en el que se define el genérico (normalmente un espacio de nombres).
luego, loadNamespace
registra las funciones de S3 en el espacio de nombres.
Entonces, en su caso, library(gmodels)
-> loadNamespace(gdata)
-> registerS3Methods(gdata)
.
Después de esto, puedes encontrarlo por:
> methods(reorder)
[1] reorder.default* reorder.dendrogram* reorder.factor*
Non-visible functions are asterisked
Sin embargo, como reorder.factor
no está adjunto en su ruta de búsqueda, no puede acceder a él directamente:
> reorder.factor
Error: object ''reorder.factor'' not found
Probablemente este es un escenario completo.
Un espacio de nombres R actúa como el entorno inmediato para todas las funciones en su paquete asociado. En otras palabras, cuando la bar()
funciones bar()
del paquete foo llama a otra función, el evaluador R primero busca la otra función en <environment: namespace:foo>
, luego en "imports.foo"
, <environment: namespace:base>
, <environment: R_GlobalEnv>
, y así sucesivamente en la lista de búsqueda devuelta al escribir search()
.
Un aspecto agradable de los espacios de nombres es que pueden hacer que los paquetes actúen como mejores ciudadanos: funciones no exportadas en <environment: namespace:foo>
y funciones en imports:foo
solo están disponibles: (a) para funciones en foo ; (b) a otros paquetes que importan desde foo ; o (c) a través de llamadas de función totalmente calificadas como foo:::bar()
.
O eso creía hasta hace poco ...
El comportamiento
Esta reciente pregunta de SO destacó un caso en el que una función bien oculta en el espacio de nombres de su paquete fue encontrada por una llamada a una función aparentemente no relacionada:
group <- c("C","F","D","B","A","E")
num <- c(12,11,7,7,2,1)
data <- data.frame(group,num)
## Evaluated **before** attaching ''gmodels'' package
T1 <- transform(data, group = reorder(group,-num))
## Evaluated **after** attaching ''gmodels
library(gmodels)
T2 <- transform(data, group = reorder(group,-num))
identical(T1, T2)
# [1] FALSE
Su causa inmediata
@Andrie respondió la pregunta original señalando que gmodels importa del paquete gdata , que incluye una función reorder.factor
que se envía al interior de la segunda llamada a transform()
. T1
difiere de T2
porque el primero se calcula por stats:::reorder.default()
y el segundo por gdata:::reorder.factor()
.
Mi pregunta
¿Cómo es que en la llamada anterior a transform(data, group=reorder(...))
, el mecanismo de despacho para reorder
encuentra y luego se despacha a gdata:::reorder.factor()
?
(Una respuesta debe incluir una explicación de las reglas de alcance que llevan desde una llamada que involucra funciones en los paquetes de estadísticas y base hasta un método aparentemente bien oculto en gdata ).
Más detalles posiblemente útiles
Ni
gdata:::reorder.factor
, ni el paquete gdata en su totalidad son importados explícitamente por gmodels . Aquí están las directivas deimport*
en el archivo NAMESPACE de gmodels :importFrom(MASS, ginv) importFrom(gdata, frameApply) importFrom(gdata, nobs)
No hay métodos para
reorder()
otransform()
en<environment: namespace:gmodels>
, ni en"imports:gmodels"
:ls(getNamespace("gmodels")) ls(parent.env(getNamespace("gmodels")))
La separación de gmodels no revierte el comportamiento de
gdata:::reorder.factor()
:gdata:::reorder.factor()
aún se envía:detach("package:gmodels") T3 <- transform(data, group=reorder(group,-num)) identical(T3, T2) # [1] TRUE
reorder.factor()
no se almacena en la lista de métodos S3 en el entorno base:grep("reorder", ls(.__S3MethodsTable__.)) # integer(0)
Los hilos de conversación R de los últimos días incluyen algunas ideas adicionales. Gracias a Andrie, Brian Diggs y Gavin Simpson, quienes (con otros) deberían sentirse libres de editar o agregar posiblemente impt. Detalles a esta pregunta.