Как проверить, содержит ли переменная лямбда-функцию? - PullRequest
2 голосов
/ 16 марта 2020

Я строю функцию, в которой основным аргументом могут быть разные вещи, например, формула, функция или лямбда-функция, и она должна обрабатывать вещи соответственно.

library(rlang)
my_func=function(x){
    if(is_function(x))
        return("X is a function")
    else if(is_lambda(x))
        return("X is a lambda")
    else if(is_formula(x))
        return("X is a formula")
    else 
        return("X is something else")
}
my_func(x=is.numeric) #function
my_func(x=A~B) #formula
my_func(x=~is.numeric(.x)) #formula too :'(
my_func(x="foo") #something else

Как вы можете видеть rlang::is_lambda не распознал лямбда-функцию. В примере файла справки они сначала используют as_function (is_lambda(as_function(x))), но это приводит к ошибке преобразования, когда x не является формулой лямбда-функции. Я бы предпочел не использовать trycatch, если это возможно, поскольку я нахожу, что это иногда приводит к нечитаемому коду и скрытым ошибкам.

Как я могу просто протестировать этот случай?

Ответы [ 2 ]

1 голос
/ 17 марта 2020

Хотя ответ Аллана работает отлично, я решил придерживаться того, что делал rlang.

Если вы посмотрите на View(rlang::as_function), вы увидите, что он прерывает только if (length(x) > 2).

Следовательно, мой код можно записать в виде:

library(rlang)
my_func=function(x){
  if(is_function(x))
    return("X is a function")
  else if(is_formula(x)){
    if(length(x) > 2)
      return("X is a formula")
    else if(is_lambda(as_function(x)))
      return("X is a lambda")
  }
  return("X is something else")
}

Это будет возвращать ожидаемый результат каждый раз.

1 голос
/ 16 марта 2020

Вы можете отменить формулу и проверить, является ли ее первый символ тильдой. Это будет означать, что любая формула без левой стороны, которая может быть приведена к лямбде, будет признана как таковая, но я предполагаю, что в любом случае это желаемое поведение.

library(rlang)

my_func=function(x){
    if(is_function(x))
        return("X is a function")
    else if(is_formula(x)){
        if(substr(deparse(x), 1, 1) ==  "~"){
            if(is_lambda(as_function(x))) 
                return("X is a lambda")
        }
        return("X is a formula")
    }
    else 
        return("X is something else")
}

my_func(x=is.numeric)
#> [1] "X is a function"
my_func(x=A~B) 
#> [1] "X is a formula"
my_func(x=~is.numeric(.x)) 
#> [1] "X is a lambda"
my_func(x="foo") 
#> [1] "X is something else"

Создано в 2020-03-16 пакетом Представлять (v0.3.0)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...