我已经在R中编写了这样的函数:
foo <- function(a, b = 1) {
...
}
但是现在我想更改默认参数b,例如:
foo(b = 2)
这是a的函数。但是R不允许这样做,这使我出错。
我该如何解决?
答案 0 :(得分:0)
您可以这样拨打foo
:foo(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::partial
或function(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
请注意,p2
和p3
在诸如mean
和min
之类的通用函数中无法正常使用。这可能是purrr:partial
中的代码如此复杂的原因。