这是我创建的一个测试函数,用于了解lapply
和闭包的交互方式。我的目标是按顺序迭代runif
函数并打印每次迭代。
Mod_delay_by <- function(delay,f){
function(x,...){
Sys.sleep(delay)
cat(".")
#f(x,...)
cat("Processing",x,"\n",sep = "")
f(x,...)
}
}
现在让我们使用lapply
来调用上面的函数:
lapply(1:3,Mod_delay_by(0.1,runif))
当我调用上面的函数时,我得到以下示例输出:
.Processing1
.Processing2
.Processing3
[[1]]
[1] 0.835246
[[2]]
[1] 0.1370997 0.4350032
[[3]]
[1] 0.1174749 0.4087628 0.7222604
我很惊讶,因为所有三个“.Processing”都在执行runif
之前到来。相反,我本来期望输出是......
.Processing1
[[1]]
[1] 0.835246
.Processing2
[[2]]
[1] 0.1370997 0.4350032
.Processing3
[[3]]
[1] 0.1174749 0.4087628 0.7222604
...因为runif
(即函数f
)之后会立即调用“.Processing”
有人可以解释为什么lapply
首先完成所有三个Processing
的打印,然后打印所有三个runifs
?
提前感谢您的帮助。
答案 0 :(得分:3)
默认情况下,函数不会向控制台打印任何内容。
.Processing1
.Processing2
.Processing3
[[1]]
[1] 0.835246
[[2]]
[1] 0.1370997 0.4350032
[[3]]
[1] 0.1174749 0.4087628 0.7222604
你来了
.Processing1
.Processing2
.Processing3
因为您使用的是cat
而其余的来自lapply
输出。
如果您更改此定义的功能
Mod_delay_by <- function(delay,f){
function(x,...){
Sys.sleep(delay)
cat(".")
#f(x,...)
cat("Processing",x,"\n",sep = "")
print(f(x,...))
}
}
然后运行
lapply(1:3,Mod_delay_by(0.1,runif))
你会得到
#.Processing1
#[1] 0.5281055
#.Processing2
#[1] 0.892419 0.551435
#.Processing3
#[1] 0.4566147 0.9568333 0.4533342
#[[1]]
#[1] 0.5281055
#
#[[2]]
#[1] 0.892419 0.551435
#
#[[3]]
#[1] 0.4566147 0.9568333 0.4533342
答案 1 :(得分:1)
显然,OP期望f()
的输出应该打印到每个调用中的控制台窗口cat()
。
与直接从控制台窗口调用函数时发生的情况类似:
> Mod_delay_by(0.1, runif)(2)
.Processing2
[1] 0.4519318 0.2331198
请注意,如果输出分配给变量,我们将不会看到任何打印的内容(cat()
的输出除外):
> result <- Mod_delay_by(0.1, runif)(2)
.Processing2
因此,如果您从控制台窗口调用一个函数并且输出而不是分配给变量,则会将其打印到控制台窗口。
现在,f()
正在从函数体中调用。这种情况不同。
f()
的输出不会打印到控制台窗口,而是返回给调用者。帮助文件?"function"
表示如果在未调用return
的情况下到达函数结尾,则返回上次计算的表达式的值。
通过编写
可以更明确地做到这一点return(f(x, ...))
因此,只有cat()
打印到控制台。 f()
的输出返回到调用lapply()
函数,该函数收集列表中的所有输出。最后,此列表仅打印到控制台,因为它未分配给变量。
如果将输出分配给变量,除了cat()
打印到控制台之外,我们不会看到任何打印内容。
> result <- lapply(1:3, Mod_delay_by(0.1, runif))
.Processing1
.Processing2
.Processing3
总而言之,R正在尝试保存输入,但结果取决于上下文:
在控制台窗口中,f()
没有分配意味着print(f())
。
在函数体中,f()
作为上次评估的表达式隐含return(f())
。