R为函数的默认参数设置新值

时间:2018-10-15 14:49:14

标签: r function

我已经在R中编写了这样的函数:

foo <- function(a, b = 1) {
    ...
}

但是现在我想更改默认参数b,例如:

foo(b = 2)

这是a的函数。但是R不允许这样做,这使我出错。

我该如何解决?

2 个答案:

答案 0 :(得分:0)

您可以这样拨打foofoo(a, b = whatever)

如果您确实需要经常将默认的b更改为相同的值,则可以创建一个新的与foo相关的功能。

您可以定义一个新函数:

# partially substitute in a `b` value
goo <- purrr::partial(foo, b = 2, .first = FALSE)

# or, a bit more explicitly,
hoo <- function(a) {foo(a, b = 2)}

或构造一个函数生成器/ factory,该函数允许您构建任意数量的与foo相关的函数

foo_builder <- function(b = 1) {
  function(a) {
    # your definition of foo goes here
    blah <- blah_f(a, b)
  }
}

现在您可以将一个b值传递给foo_builder,它将把等效的函数返回到foo(a, b = whatever_you_passed_to_foo_builder)

goo <- foo_builder(2)
goo(a = ...)

例如,

foo_builder <- function(b = 1){
   function(a){
     message(b)
     a + b
   }
 }

现在,当内部函数由foo_builder定义时,它将采用b环境可用的foo_builder值。默认情况下为1,但可以更改。

例如,

# default
foo_builder()(1)
1
[1] 2

# with b=2 in the closure returned by foo_builder
b <- 2
fb <- foo_builder(b)
fb(1)
2
[1] 3

一个评论者建议您以这种方式进行关闭时应强制对b进行评估;由于以下原因:

b <- 2
fb <- foo_builder(b)
b <- 3
fb(1)
# 3
# [1] 4

所以也许重写foo_builder:

foo_builder <- function(b = 1){
   force(b)
   function(a){
     message(b)
     a + b
   }
 }

答案 1 :(得分:0)

您在foo(b = 2)中的代码是函数应用程序:如果一切都按预期工作,它将为您提供值而不是函数。

您可以使用formals修改参数的默认值:

foo <- function(a, b = 1) {
  a + b
}

formals(foo)$b <- 2
foo
#function (a, b = 2) 
# {
#     a + b
# }

如果您不想直接修改foo,则有几种选择:

1)首先复制,以后更改

foa <- foo
formals(foa)$b <- 42

人们可能会考虑使用"formals<-"作为快捷方式,但是由于您需要提供完整的参数列表(使用alist而不是list可能会很复杂,因为前者可以空参数):

"formals<-"(foo, , list(b=2))  # trying it with `list` 
function (b = 2)  # we lost one argument! 
{
    a + b
} 
"formals<-"(foo, , alist(a=, b=42))  # this one is better!
function (a, b = 42) 
{
  a + b
}

2)按照其他答案中的建议使用purr::partialfunction(a) foo(a,b=42)

3)第三种方式……实际上可以编写一个非常简单的函数(我将其称为p2),该函数会更改函数的默认参数的 some 并返回更改后的函数:

p2 <- function(f, l){
  formals(f)[names(l)] <- l
  f
}

p2(foo, list(b=42)) # changing a default: function (a, b = 42) a+b
p2(foo, alist(b=)) # removing a default: function (a, b) a+b
p2(foo, list(c="bingo") # adding an argument: function (a, b = 2, c = "bingo") a+b

修改版本:

p3 <- function(f, ...){
  l <- as.list(sys.call())[-(1L:2L)]  # code from `alist`
  formals(f)[names(l)] <- l
  f
  }

现在用法变得更短:

p3(foo, b=43) # function (a, b = 43) a+b
p3(foo, b=) # function(a,b) a+b

请注意,p2p3在诸如meanmin之类的通用函数中无法正常使用。这可能是purrr:partial中的代码如此复杂的原因。