从功能内部打印到R控制台
我想修改R函数中控制台打印的行为,以恢复与全局环境中相同的行为 正如您可以调用从功能内部打印到R控制台,r,console,cat,error-checking,R,Console,Cat,Error Checking,我想修改R函数中控制台打印的行为,以恢复与全局环境中相同的行为 正如您可以调用browser()进入函数环境并访问局部变量一样,我只想让表达式打印到控制台 我们的目标是提供一种灵活、快速的方法来评估许多(几十个)表达式,以便进行代码检查和理解中间输出的统计特性。我想在运行中执行此操作,而不必使用调试器进入函数,因为这需要额外的手动控制,也不必编写冗余语句,如print(“x^2”);打印(x^2),我可能会这样做,但稍后会在代码开发过程中进行更持久的代码检查 我想到的是:编写一个函数log.to
browser()
进入函数环境并访问局部变量一样,我只想让表达式打印到控制台
我们的目标是提供一种灵活、快速的方法来评估许多(几十个)表达式,以便进行代码检查和理解中间输出的统计特性。我想在运行中执行此操作,而不必使用调试器进入函数,因为这需要额外的手动控制,也不必编写冗余语句,如print(“x^2”);打印(x^2)
,我可能会这样做,但稍后会在代码开发过程中进行更持久的代码检查
我想到的是:编写一个函数log.to.console()
,以便输出以下内容:
myfunlog = function(x){
log.to.console()
a1 = sqrt(x)
a2 = exp(x)
a1;a2;log(x);x^2
return(a1*a2)
}
ans = myfunlog(2)
[1] a1
[1] 1.414214
[1] a2
[1] 7.389056
[1] log(x)
[1] 0.6931472
[1] x^2
[1] 4
我有一个解决方案,它不是我想要的,但是,多亏了Hadley的高级R页面的表达式和范围,我想出了这个函数:
print.to.console = function(...){
dots = pryr::named_dots(...)
p = parent.frame()
for( dot in dots){
print(dot)
print(eval(dot, envir = p))
}
}
myfunprint = function(x){
a1 = sqrt(x)
a2 = exp(x)
print.to.console(
a1, a2, log(x), x^2
)
return(a1*a2)
}
ans = myfunprint(2)
# Which gives the output I want:
a1
[1] 1.414214
a2
[1] 7.389056
log(x)
[1] 0.6931472
x^2
[1] 4
更新:我现在可以用一个函数调用显式作用域调用它,而以前我必须在
myfunprint()中使用environment(print.to.console)=environment()
。但是,我还是想弄清楚如何实现上面描述的log.to.console()
功能。有什么想法吗?我建议用字符标签和值构建一个命名列表
prtplus <- function(...){ dots <- substitute(list(...))[-1]
anames <- sapply(dots, deparse); setNames( list(...), anames) }
print
对于globalenv()
是多余的,但在函数中需要:
myfunlog = function(x){
a1 = sqrt(x)
a2 = exp(x)
print( prtplus(
a1, a2, log(x), x^2
))
return(a1*a2)
}
ans = myfunlog(2)
$a1
[1] 1.414214
$a2
[1] 7.389056
$`log(x)`
[1] 0.6931472
$`x^2`
[1] 4
您还可以将print
构建到prtplus
:
prtplus <- function(...){ dots <- substitute(list(...))[-1]
anames <- sapply(dots, deparse); print(setNames( list(...), anames)) }
prtplusprint
功能执行此操作。我不明白存在什么问题。你能举一个小例子,说明print
无法生成控制台的输出吗?我希望表达式与输出一起打印,如本文所示。这是因为在实际用例中,我们讨论的是几十个长表达式,我不想单独命名。我只想通过它们的表达式调用来指代它们。我也不喜欢打印两次,例如打印(“x^2”);打印(x^2),以便每次修改表达式时都必须修改字符串。如果我在print
中错过了此功能,请解释。尽管如此,我还是希望调用一个可以调用一次的log.to.console()
函数,就像调用browser()函数一样。谢谢如果将表达式定义为函数中的对象,可以执行类似于all_vars=ls()的操作;对于ls中的(i){print(i);print(get(i))}
。这样好吗?我不知道你想要的log.to.console
是什么,它与myfunlog
有什么不同(这只是一个示例函数吗?)你希望其中有多少是动态的?打印表达式而不仅仅是对象真的那么重要吗?为什么不让一个debug
参数以默认值debug=FALSE
传递给您的函数,并让一些if语句用于打印额外的内容,if(debug){print.expressions.to.console()}
。这很酷,圆点添加了一个循环显示,cat
.cool,我们都有一个可以很好地包装表达式和打印的解决方案。我更多地讨论了第一个(主要)问题:是否有一种方法可以通过在感兴趣的函数体中添加对某个log.to.console()
函数的调用来获得要输出的表达式。我知道这是一个更难的问题。。。但并非不可能?我认为您可能需要修改parse
或eval
的行为,以便将每个表达式都回显到控制台。(这远高于我的工资等级。)你可能想看看跟踪功能是如何运作的。仔细想想,真正需要的是对
prtplus <- function(...){ dots <- substitute(list(...))[-1]
anames <- sapply(dots, deparse); print(setNames( list(...), anames)) }
prtplus <- function(...){ dots <- substitute(list(...))[-1]
anames <- sapply(dots, deparse)
vals <- setNames( list(...), anames)
for(i in seq_along(vals)){
cat( c( names(vals)[i], "\n", round( vals[[i]],6),"\n") ) }
}
ans = myfunlog(2)
#----output to console---
a1
1.414214
a2
7.389056
log(x)
0.693147
x^2
4