Может ли поведение функции R меняться в зависимости от количества полученных аргументов? - PullRequest
0 голосов
/ 28 марта 2019

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

...

f <- function(x)
  UseMethod("g")

f.numeric <- function(x)
  return(x^2)

f.character <- function(x)
  return("Hey, dude. WTF are you doing? Don't give me characters!")

...

Теперь предположим, что я хочу, чтобы f мог получать два числа в качестве входных данных и возвращать их сумму, не теряя предыдущую функциональность. Как мне этого добиться?

Ответы [ 5 ]

1 голос
/ 28 марта 2019

Не могли бы вы переписать функцию, чтобы сделать проверки самостоятельно? например ...

f <- function(x, y=NA){
  if (all(is.numeric(c(x,y))) & !is.na(y)){
    return(x+y)
  }else if(is.numeric(x)){
    return(x^2)
  }else if(is.character(x)){
    return("Hey, dude. WTF are you doing? Don't give me characters!")
  }else{
    return("Hey, dude. I don't know what you are giving me?!")
  }
}
1 голос
/ 28 марта 2019

С многоточием это легко возможно:

f <- function(x,...)
{
  if(missing(...))
  {
    if(is.numeric(x)) return(x^2)
    if(is.character(x)) return("Hey, dude. WTF are you doing? Don't give me characters!")
  }else
  {
    if(any(is.character(c(x,...)))  return("Hey, dude. WTF are you doing? Don't give me characters!"))
    return(x+..1)
  }
}

> f("foo")
[1] "Hey, dude. WTF are you doing? Don't give me characters!"
> f(4)
[1] 16
> f(4,5)
[1] 9
0 голосов
/ 28 марта 2019

Если вы хотите продолжать использовать S3, вы можете использовать ...length() (> = R 3.4.2 ):

f <- function(...)
  UseMethod("f")

f.numeric <- function(...)
  if(...length() == 1) ..1^2 else sum(...) 

f.character <- function(...)
  return("Hey, dude. WTF are you doing? Don't give me characters!")

f(2)
#[1] 4

f(3,4)
# [1] 7
0 голосов
/ 28 марта 2019

Если то, что вы ищете, это что-то вроде сигнатур метода C [1], то нет, я не знаю, что R имеет что-то подобное.

Самое близкое, что мне известно в R, это то, что у вас есть «суперфункция», которая принимает все аргументы, а затем набор подфункций, на которые распространяется эта суперфункция. Например, рассмотрим (то, что я обрисовал в общих чертах ниже, не отличается функционально от ответа Julian_Hn. Разница между использованием эллипсов и явным присвоением имен аргументам заключается в степени контроля того, что пользователь может передать функции. Если вы используете эллипсы, ваш тест на наличие аргумента будет выглядеть иначе)

super_function <- function(x = NULL, y = NULL){
  if (!is.null(x) & is.null(y)){
    if (is.character(x)){
      sub_function_xchar(x)
    } else if {
      (is.numeric(x)){
        sub_function_xnum(x)
      }
    } else {
      sub_function_xelse(x)
    }
  } else {
    if (!is.null(x) & !is.null(y)){
      if (is.character(x) & is.character(y)){
        sub_function_xychar(x, y)
      } else {
        # Okay, I think you might get the point now
      }
    }
  }
}

sub_function_xchar <- function(x){
  # whatever you want to do with x as a character
}

sub_function_xnum <- function(x){
  # whatever you want to do with x as a numeric
}

sub_function_xelse <- function(x){
  # whatever you want to do with any other class of x
}

sub_function_xychar <- function(x, y){
  # whatever you want to do with x and y as characters
}

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

[1] Не уверен, правильно ли я понял термин, но функциональность в C, что многие методы могут иметь одно и то же имя, но они должны быть уникальными для коллекции и типа аргументов, которые они принимают.

0 голосов
/ 28 марта 2019

Не уверен, что это то, что вам нужно, но, возможно, это поможет:)

sum_them <- function(var1, var2, na.rm = F)
{
  if(all(is.numeric(c(var1, var2)))) return(sum(c(var1, var2), na.rm = na.rm))
  return("non numeric argument")

}

sum_them("test", "this")
sum_them("test", 10)
sum_them(5, "this")
sum_them(5, 10)
sum_them(NA, 10)
sum_them(NA, 10, na.rm = T)

Вывод

> sum_them("test", "this")
[1] "non numeric argument"
> sum_them("test", 10)
[1] "non numeric argument"
> sum_them(5, "this")
[1] "non numeric argument"
> sum_them(5, 10)
[1] 15
> sum_them(NA, 10)
[1] NA
> sum_them(NA, 10, na.rm = T)
[1] 10

Обновлена ​​функция, так как я не получил что-то другоеесли это просто 1 число.

Логика позади: если есть только 1 параметр (var1), делайте с ним что угодно, но попробуйте в случае, если он не числовой.Если все параметры числовые, суммируйте их.иначе вернуть некоторую строку.

   sum_them <- function(var1, ..., na.rm = F)
{
  if(missing(...)) tryCatch({var1 <- var1^2}, warning = function(w){}, error = function(e){})
  if(all(is.numeric(c(var1, ...)))) return(sum(c(var1, ...), na.rm = na.rm))
  return("non numeric argument")

}

новый вывод:

> sum_them("test", "this")
[1] "non numeric argument"
> sum_them("test", 10)
[1] "non numeric argument"
> sum_them(5, "this")
[1] "non numeric argument"
> sum_them(5, 10)
[1] 15
> sum_them(NA, 10)
[1] NA
> sum_them(NA, 10, na.rm = T)
[1] 10
> sum_them(NA, na.rm = T)
[1] 0
> sum_them(10, na.rm = T)
[1] 100
> sum_them(10)
[1] 100
> sum_them("test")
[1] "non numeric argument"
> sum_them(10,10,10,10, NA)
[1] NA
> sum_them(10,10,10,10, NA, na.rm = T)
[1] 40
> sum_them(10,10,10,test, NA, na.rm = T)
[1] "non numeric argument"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...