我想了解R在将参数传递给函数,创建变量副本等时使用的逻辑与内存使用情况有关.它什么时候实际创建变量的副本而不是仅仅传递对该变量的引用?特别是我很好奇的情况是:
f <- function(x) {x+1}
a <- 1
f(a)
Run Code Online (Sandbox Code Playgroud)
是a字面意思传递还是被传递的参考?
x <- 1
y <- x
Run Code Online (Sandbox Code Playgroud)
复制参考?什么时候不是这样的?
如果有人能向我解释这一点,我将非常感谢.
"R通过了承诺,而不是价值观.承诺在首次评估时被强制执行,而不是在通过时.",请参阅G. Grothendieck的回答.另请参阅Hadley的书中的这个问题.
在简单的例子中
> funs <- lapply(1:10, function(i) function() print(i))
> funs[[1]]()
[1] 10
> funs[[2]]()
[1] 10
Run Code Online (Sandbox Code Playgroud)
可以考虑这种不直观的行为.
但是,我发现自己经常在日常发展过程中陷入这个陷阱.我遵循一个相当功能的编程风格,这意味着我经常有一个函数A返回一个函数B,其中B在某种程度上取决于调用A的参数.依赖性不像上面的例子那么容易看,因为计算很复杂并且有多个参数.
忽略这样的问题导致难以调试问题,因为所有计算都顺利进行 - 除了结果不正确.只有对结果的明确验证才能揭示问题.
最重要的是,即使我注意到这样的问题,我也不确定我需要哪些变量,哪些变量不需要force.
我怎样才能确保不陷入这个陷阱?是否有任何编程模式可以防止这种情况,或者至少确保我发现存在问题?
我不确定R中的承诺是做什么的
如果一个人跑
a = lapply(seq_len(2), function(n) { function() {n}})
b = lapply(seq_len(2), function(n) {n})
Run Code Online (Sandbox Code Playgroud)
我们可以看到
a[[1]]() # == 2
b[[1]] # == 1
Run Code Online (Sandbox Code Playgroud)
我理解R使用promise的对象并懒惰地在其环境中计算表达式,但我不明白为什么为每个函数创建的不同环境不会包含它们自己的n值.
[[1]]
function ()
{
n
}
<environment: 0x7f9b2416ad18>
[[2]]
function ()
{
n
}
<environment: 0x7f9b2416ab20>
as.list(environment(a[[1]]))
$n
[1] 2
as.list(environment(a[[2]]))
$n
[1] 2
Run Code Online (Sandbox Code Playgroud)
是否有可能以某种方式通过lapply函数修复语义?
lapply
function (X, FUN, ...)
{
FUN <- match.fun(FUN)
if (!is.vector(X) || is.object(X))
X <- as.list(X)
.Internal(lapply(X, FUN))
}
<bytecode: 0x7f9b25150f18>
<environment: namespace:base>
Run Code Online (Sandbox Code Playgroud)
PS:重新聚焦的问题
编辑:具体来说,是否可以编写一个 …
我有下面的R代码(这个问题的最后一部分),在最后一行之后,我希望得到一个4"retFun"函数的列表,每个函数用不同的x初始化,以便得到以下结果
funList[[1]](1) == 7 #TRUE
funList[[2]](1) == 8 #TRUE
Run Code Online (Sandbox Code Playgroud)
等等,但我似乎得到的是
funList[[1]](1) == 10 #TRUE
funList[[2]](1) == 10 #TRUE
Run Code Online (Sandbox Code Playgroud)
好像列表中的每个函数都具有相同的x值
creatFun <- function(x, y)
{
retFun <- function(z)
{
z + x + y
}
}
myL <- c(1,2,3,4)
funList <-sapply(myL, creatFun, y = 5)
Run Code Online (Sandbox Code Playgroud)