从功能内部打印到R控制台

从功能内部打印到R控制台,r,console,cat,error-checking,R,Console,Cat,Error Checking,我想修改R函数中控制台打印的行为,以恢复与全局环境中相同的行为 正如您可以调用browser()进入函数环境并访问局部变量一样,我只想让表达式打印到控制台 我们的目标是提供一种灵活、快速的方法来评估许多(几十个)表达式,以便进行代码检查和理解中间输出的统计特性。我想在运行中执行此操作,而不必使用调试器进入函数,因为这需要额外的手动控制,也不必编写冗余语句,如print(“x^2”);打印(x^2),我可能会这样做,但稍后会在代码开发过程中进行更持久的代码检查 我想到的是:编写一个函数log.to

我想修改R函数中控制台打印的行为,以恢复与全局环境中相同的行为

正如您可以调用
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)) }

prtplus
print
功能执行此操作。我不明白存在什么问题。你能举一个小例子,说明
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