2009-10-14 9 views
41

Digamos que tengo un montón de funciones, cada una con algo como MyFunction.1, etc. Quiero pasar estas funciones a otra función, que imprime un informe pequeño. Idealmente, me gustaría poder etiquetar secciones de un informe mediante el cual se está utilizando la función para generar los resultados.Obteniendo un nombre de función como una cadena

¿Hay alguna manera agradable de obtener el nombre de una función predefinida como una cadena?

Respuesta

7

que pueden conducir a parse(eval(...)) momento en el que usted está abierto a esa crítica:

R> library(fortunes) 
R> fortune("parse") 

If the answer is parse() you should usually rethink the question. 
    -- Thomas Lumley 
     R-help (February 2005) 

R> 

también lo hacen sus funciones han de ser llamado MyFunction.1 etc pp?

+0

Hah - Temía obtener esa fortuna. Solo quería poder tener una función a la que pueda llamar como compare.distribution.methods (c (two.choice, go.left, simple.random.sample), y obtener una tabla de resultados para cada método en el vector. Lo bueno de tener es no tener que pasar un vector de etiquetas con los nombres que quiero, pero ciertamente es otra opción. Esperaba algo que lo hiciera por mí. Si esto no es parte de la R fluya, entonces es tanto mejor que se responda esta pregunta. – HamiltonUlmer

+1

El envío del método S3 lo hace por usted! No tema al "OO", este sería un buen ejemplo simple para empezar a usarlo. Si tan solo tuviera algún tipo de y documentos sencillos para señalarle ... Tal vez el libro de Chambers "Software for Data Analysis" del año pasado? –

2

Cuando una función se pasa como un objeto, pierde su nombre. Véase, por ejemplo, los resultados de las siguientes líneas:

str(lm) 
lm 

Puede obtener los argumentos y el cuerpo de la función, pero no el nombre.

Mi sugerencia sería construir una lista con nombre de funciones, en el que el nombre podría ser impresas

> somefns <- list(lm=lm, aggregate=aggregate) 
> str(somefns) 
List of 2 
$ lm  :function (formula, data, subset, weights, na.action, method = "qr", 
    model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, 
    contrasts = NULL, offset, ...) 
$ aggregate:function (x, ...) 

> somefns[[1]](dist ~ speed, data=cars) 

Call: 
somefns[[1]](formula = dist ~ speed, data = cars) 

Coefficients: 
(Intercept)  speed 
    -17.58   3.93 

> names(somefns)[[1]] 
[1] "lm" 
+0

Dos buenas alternativas [acabamos de publicar aquí] (http://stackoverflow.com/questions/25621108/ keeping-function -names-when-stored-in-an-object) –

16

Otro enfoque sería pasar los nombres de las funciones en su función de informe y, a continuación, obtener la funciona con el comando get(). Por ejemplo:

function.names <- c("which","all") 
fun1 <- get(function.names[1]) 
fun2 <- get(function.names[2]) 

Entonces usted tiene los nombres en su vector carácter original, y las funciones tienen nombres nuevos a medida que los defina. En este caso, la función all ahora se llama como fun2:

> fun2(c(TRUE, FALSE)) 
[1] FALSE 

O, si usted realmente quiere mantener los nombres de las funciones originales, simplemente asignarlos a nivel local con la función de asignación:

assign(function.names[2], get(function.names[2])) 

Si ejecuta este comando en este momento, terminará con la función all en su ".GlobalEnv". Puede ver esto con ls().

+1

No fue realmente la pregunta de los autores y no es tan agradable w orkaround. Ver match.call (diversión) [2] a continuación. – Dennis

7

Puede obtener los argumentos no evaluados de una función a través de match.call.Por ejemplo:

> x <- function(y) print(match.call()[2]) 
> x(lm) 
lm() 
+1

Es cierto, no es útil aquí. Si dice "z <- lm" y luego x (z), obtiene "z", no "lm". – Harlan

+0

Es cierto, aunque no está claro cuál es el comportamiento correcto en ese momento. ¿Qué función es "canónica" y debería imprimirse? –

+0

En un lenguaje funcional, el nombre de la función no es realmente importante. Puede cambiar el nombre fácilmente de funciones o tener funciones sin nombres. La función match.call simplemente te da el nombre de la variable que tenía la función cuando se la llamaba, por lo que en ese sentido, está haciendo lo único que puede hacer. No sé que "canónico" realmente entra en juego ... – Harlan

1

qué pasa con esto:

deparse(quote(foo.bar)) 
40

que estaba buscando la misma cosa, y recordé library(foo) no necesitan comillas, esto es lo que hace:

package <- as.character(substitute(package)) 
+4

¡buena observación! objectName = as.character (quote (object)) funciona igual – RockScience

+0

Buen truco, gracias. – tunnuz

+0

¿cómo apareció el código de 'lbrary'? –

2

Solo quiero dar un ejemplo para mostrar la ventaja y la limitación en este tema:

I querer "salvar" a una función con su nombre, como una opción que sería utilizado en otra función:

R> foreach(..., .combine=test_fun) {...} 

El test_fun es el nombre de la función, y por supuesto

R> mode(test_fun) 
[1] "function" 

Cuando Úselo en foreach, solo necesito el nombre de la función, mientras que test_fun puede ser una función existente (ej. cbind). Así, test_fun sean cedidos por

R> test_fun <- get('cbind') 

o

R> test_fun <- assign('cbind', get('cbind')) 

Así, tienes la función aquí

R> test_fun 
function (..., deparse.level = 1) 
.Internal(cbind(deparse.level, ...)) 

realidad, el nombre original no puede ser mantenida, por lo que no tienen forma de convertir test_fun a la secuencia "cbind".

R> deparse(substitute(test_fun)) 
[1] "test_fun" 

que por desgracia tienen que deparse el código foreach por lo que desee el nombre original mostrada en la cadena. Esto significa que la única forma es guardar 'cbind' como una cadena y crear dicho objeto de función no trae ningún beneficio en este caso.

Cuestiones relacionadas