假设我有以下函数:
## Just an example
f = function() {
for(i in 1:10000)
cat(i)
return(1)
}
当我调用f()
时,有没有一种方法可以停止cat
在屏幕上打印(不改变函数本身的任何方式)?
提问原因
我的学生上传他们的R文件。然后我运行这些脚本并检查它们是否正确。偶尔会有学生留下cat
命令。如果这个命令出现在一个很长的for循环中,那么这将特别烦人。
在Linux上,您可以使用sink()
调用将输出重定向到/dev/null
(或者在其他操作系统上重定向到临时文件,参见?tempfile
):
sink(file="/dev/null")
f()
sink()
这应该可以工作吗?
oldcat = cat
cat = function( ..., file="", sep=" ", fill=F, labels=NULL, append=F ) {}
f()
cat = oldcat
只需将cat
替换为空的function
,然后在完成后将其设置回来。
cat <- function(...) {}
会更简单。 - hadleycat <- list
,只要cat
仅出现在函数中。 - G. Grothendieckrm(cat)
会还原 cat
,并删除全局环境中的版本,以便它不会掩盖基础版本。此外,我们可以消除对 oldcat
的需求,因为它始终可以被引用为 base::cat
。 - G. Grothendieckinvisible()
和capture.output()
可以实现你想要的效果:f <- function() {
cat("Hello")
return(TRUE)
}
f1 <- function() {
invisible(capture.output(f()))
}
x <- f1()
这也可以工作:
f2 <- function() {
tmp <- tempfile()
sink(tmp)
on.exit(sink())
on.exit(file.remove(tmp), add = TRUE)
invisible(force(f()))
}
x <- f2()
这里有一个有趣的技巧,可以注释掉函数中所有的cat()
。不确定这样做是否会导致错误或破坏函数:
foo <- deparse(f)
f <- eval(parse(text=gsub("cat","#cat",foo)))
f()
[1] 1
另一个选择基本上是Juba的答案,使用sink,但您可以使用Defaults
包来更改cat
的默认行为。 file
参数将其输出沉入文件中。 所以:
library("Defaults")
setDefaults(cat,file="sink.txt")
f()
确保只有cat
的输出被接收,而不是print
等其他内容。然而,这会极大地降低运行时间,因为现在每次运行cat()
时都会打开和关闭文件。
gsub("^cat$", "#cat", foo)
。 - aL3xapurrr
库中的quietly()
函数可以创建一个安静版本的函数:
library(purrr)
f <- function() {
cat("Hello")
return(TRUE)
}
f2 <- quietly(f)
f2()
#> $result
#> [1] TRUE
#>
#> $output
#> [1] "Hello"
#>
#> $warnings
#> character(0)
#>
#> $messages
#> character(0)
sink
非常有用。但它也会使函数的返回值失效。 - Sacha Epskampf()
的输出分配给一个对象。 - Gavin Simpsoncapture.output(x <- f())
的操作。 - hadley