Получение имени функции, переданной в качестве аргумента функции - PullRequest
0 голосов
/ 29 октября 2018

Фон

Функция передается в качестве аргумента функции. Проблема относится к:

  • получение имени этой функции в виде строки для удобного последующего манипулирования
  • поиск этой функции в пакете, из которого вызывается
  • понимание :: и ::: вызовы

Пример

Функция fun_tst выполняет функцию FUN на x:

fun_tst <- function(x = 1:100, FUN = mean) {
    return(FUN(x))
}

mean

fun_tst()
# [1] 50.5

sum

fun_tst(x = 1:1e3, FUN = sum)
# [1] 500500

Проблема

fun_tst <- function(x = 1:100, FUN = mean) {
    msg <- paste("Executing function", FUN)
    print(msg)
    return(FUN(x))
} 


fun_tst(x = 1:1e3, FUN = sum)

Ошибка в вставке («Выполнение функции», FUN): невозможно принудительно ввести тип 'встроенный' в вектор типа 'символ'


Попытка

1)

Интересно, что print может обрабатывать FUN объект, но результаты возвращают тело функции.

fun_tst <- function(x = 1:100, FUN = mean) {
    print(FUN)
    return(FUN(x))
} 


fun_tst(x = 1:1e3, FUN = sum)

function (..., na.rm = FALSE) .Primitive ("sum") [1] 500500

2) subsitute

fun_tst <- function(x = 1:100, FUN = mean) {
    fun_name <- substitute(FUN)
    msg <- paste("Executing function", fun_name, collapse = " ")
    print(msg)
    return(FUN(x))
} 


fun_tst(x = 1:1e3, FUN = sum)

>> fun_tst(x = 1:1e3, FUN = sum)
[1] "Executing function sum"
[1] 500500

Почти там, но выглядит как полный беспорядок при использовании с :: как в:

>> fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
[1] "Executing function :: Executing function dplyr Executing function glimpse"
 int [1:1000] 1 2 3 4 5 6 7 8 9 10 ..

Желаемые результаты

fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
# Executing function glimpse from package dplyr
int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...

fun_tst(x = 1:1e3, FUN = sum)
# Executing function sum from package base

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

Если вы используете deparse() и substitute, вы получите желаемый результат, см. Аналогичный пост о передаче имен переменных в plot(), https://stackoverflow.com/a/9666650/1993932.

fun_tst <- function(x = 1:100, FUN = mean) {
  message(paste("Executing function",deparse(substitute(FUN))))
  return((FUN(x)))
}
> fun_tst(x = 1:1e3, FUN = sum)
Executing function sum
[1] 500500

> fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
Executing function dplyr::glimpse
 int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...

Если вы хотите, чтобы сообщение представляло собой символьный вектор, замените message на print.

0 голосов
/ 29 октября 2018

Вы почти со второй попытки (используя substitute). Проблема возникает из-за того, что R преобразует language объекты в символы:

> as.character(substitute(dplyr::glimpse))
[1] "::"      "dplyr"   "glimpse" 

Учитывая это, неудивительно, что paste искажает это таким образом. Я бы исправил это, просто обработав два случая:

fun_tst <- function(x = 1:100, FUN = mean) {
  fun_name <- substitute(FUN)
  if (length(fun_name) == 1) {
    msg <- paste("Executing function", fun_name, "from package base")
  } else {
    msg <- paste("Executing function", fun_name[3], "from package", fun_name[2])
  }
  print(msg)
  return(FUN(x))
} 

Это работает на обоих ваших примерах:

> fun_tst(x = 1:1e3, FUN = sum)
[1] "Executing function sum from package base"
[1] 500500
> fun_tst(x = 1:1e3, FUN = dplyr::glimpse)
[1] "Executing function glimpse from package dplyr"
 int [1:1000] 1 2 3 4 5 6 7 8 9 10 ...

Однако, как написано, он будет считать, что все функции в глобальной среде относятся к base, даже если они определены пользователем или введены с помощью вызова library. Если это ваш вариант использования, не говорите явно "из базы пакета".

...