将R函数的默认参数y
定义为等于其他参数x
时。例如:function(x,y=x)
。我发现如果在使用我的默认参数(x
)之前更改了另一个参数(y
),它也会更改y的值。
据我所知,它与“延迟复制直到修改”有关,但这真的是理想的行为吗?
以下是一个完整的例子:
oh_my <- function(x, y=x){
x <- rev(x)
y <- rev(y) # the value of y here actually is rev of initial x!
print(y)
}
oh_my(1:5)
[1] 1 2 3 4 5
一个简单的解决方案是:
ok <- function(x, y=NULL){
if(is.null(y)){
y<-x
}
x <- rev(x)
y <- rev(y)
print(y)
}
ok(1:5)
[1] 5 4 3 2 1
但我真的很喜欢第一个选项中的默认值很明显(包括自动生成的帮助文件)。
另一个解决方案是:
pfiouu <- function(x, y=x){
y <- rev(y) # the value of y here actually is rev of initial x!
x <- rev(x)
print(y)
}
pfiouu(1:5)
[1] 5 4 3 2 1
但对我而言,pfiouu
和oh_my
给出不同的结果似乎很尴尬,因为两条交换的行没有明确提及其他变量,但产生不同的结果!
我是否错过了一个良好的做法,可以保持默认显而易见并避免这种陷阱?
答案 0 :(得分:0)
根据MrFlick的建议,在函数开头添加force(y)
可以强制评估y
并防止出现类似问题。在这种高级编程语言中,这是一种理想的行为,因为R仍然是开放的。
no_surprise<- function(x, y=x){
force(y)
x <- rev(x)
y <- rev(y)
print(y)
}
no_surprise(1:5)
[1] 5 4 3 2 1
正如所料。