web-dev-qa-db-fra.com

Obtenir un nom de fonction sous forme de chaîne

Disons que j'ai un tas de fonctions, chacune avec quelque chose commeMyFunction.1, etc. Je veux passer ces fonctions dans une autre fonction, qui imprime un petit rapport. Idéalement, j'aimerais pouvoir étiqueter des sections d'un rapport par lesquelles la fonction est utilisée pour générer les résultats.

Y a-t-il donc de bonnes façons d'obtenir le nom d'une fonction prédéfinie sous forme de chaîne?

47
HamiltonUlmer

Je voulais la même chose, et je me suis souvenu que library(foo) n'avait pas besoin de guillemets, c'est ce qu'il fait:

package <- as.character(substitute(package))
45
nfultz

Une autre approche consiste à passer les noms des fonctions dans votre fonction de rapport, puis à récupérer les fonctions elles-mêmes avec la commande get(). Par exemple:

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

Ensuite, vous avez les noms dans votre vecteur de caractères d'origine et les fonctions ont de nouveaux noms tels que vous les avez définis. Dans ce cas, la fonction all est maintenant appelée comme fun2:

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

Ou, si vous voulez vraiment conserver les noms de fonction d'origine, affectez-les simplement localement avec la fonction assign:

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

Si vous exécutez cette commande maintenant, vous vous retrouverez avec la fonction all dans votre ".GlobalEnv". Vous pouvez le voir avec ls().

16
Shane

Cela peut conduire à parse(eval(...)) à quel point vous êtes ouvert à cette critique:

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

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

R>

Vos fonctions doivent donc être appelées MyFunction.1 etc pp?

7
Dirk Eddelbuettel

Vous pouvez obtenir les arguments non évalués d'une fonction via match.call. Par exemple:

> x <- function(y) print(match.call()[2])
> x(lm)
lm()
6
Jonathan Chang

Lorsqu'une fonction est transmise en tant qu'objet, elle perd son nom. Voir, par exemple, les résultats des lignes suivantes:

str(lm)
lm

Vous pouvez obtenir les arguments et le corps de la fonction, mais pas le nom.

Ma suggestion serait de construire une liste nommée de fonctions, où le nom pourrait être imprimé:

> 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"
3
Harlan

Je veux juste fournir un exemple pour montrer les avantages et les limites de ce problème:

Je veux "enregistrer" une fonction avec son nom, comme option qui serait utilisée dans une autre fonction:

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

Le test_fun est le nom de la fonction, et bien sûr

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

Quand je l'utilise dans foreach, j'ai juste besoin du nom de la fonction, tandis que test_fun peut être une fonction existante (par exemple cbind). Alors, test_fun est attribué par

R> test_fun <- get('cbind')

ou

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

Donc, vous avez la fonction ici

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

en fait, le nom d'origine ne peut pas être conservé, vous n'avez donc aucun moyen de convertir test_fun retour à la chaîne "cbind".

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

J'ai malheureusement besoin d'analyser le code foreach donc je veux que le nom d'origine soit affiché dans la chaîne. Cela signifie que le seul moyen consiste à enregistrer 'cbind' en tant que chaîne et la création d'un tel objet fonction n'apporte aucun avantage dans ce cas.

3
lionelc

et ça:

deparse(quote(foo.bar))
2
mariotomo