有没有办法让R函数判断它是从`for`还是`while`循环调用的?

时间:2012-08-06 01:27:08

标签: r for-loop scope while-loop

问题的标题几乎说明了:R函数是否有办法找出它是直接调用还是从forwhile循环内部调用?无论函数是直接调用还是从其中一个循环内部调用,sys.frame(0)parent.frame(1)都会返回.GlobalEnv。那么,还有其他方法吗?

感谢。

4 个答案:

答案 0 :(得分:2)

这不是一个明确的答案,但我认为您的解决方案是查看sys.status,特别是sys.parents。第二个例子是在另一个函数内和循环内调用函数的时候。如果不明确知道,不确定如何区分它。

test <- function() sys.status()

for(i in 1:2){
  print(test())
 }


## $sys.calls
## $sys.calls[[1]]
## print(test())
## 
## $sys.calls[[2]]
## test()
## 
## $sys.calls[[3]]
## sys.status()
## 
##
## $sys.parents
## [1] 0 0 2
##
## $sys.frames
## $sys.frames[[1]]
## <environment: 0x0479a1c8>
##
## $sys.frames[[2]]
## <environment: 0x0479a2fc>
##
## $sys.frames[[3]]
## <environment: 0x0479a334>
##
##
## $sys.calls
## $sys.calls[[1]]
## print(test())
##
## $sys.calls[[2]]
## test()
## 
## $sys.calls[[3]]
## sys.status()
##
##
## $sys.parents
## [1] 0 0 2
## 
## $sys.frames
## $sys.frames[[1]]
## <environment: 0x047993cc>
## 
## $sys.frames[[2]]
## <environment: 0x04799570>

## $sys.frames[[3]]
## <environment: 0x047995a8>

test()

## $sys.calls
## $sys.calls[[1]]
## test()
## 
## $sys.calls[[2]]
## sys.status()
## 
## 
## $sys.parents
## [1] 0 1
## 
## $sys.frames
## $sys.frames[[1]]
## <environment: 0x04775500>
##   
##   $sys.frames[[2]]
## <environment: 0x04775538>

test_sq <- function() test()

for(i in 1:2){
  print(test_sq())
 }

## $sys.calls
## $sys.calls[[1]]
## print(test_sq())
## 
## $sys.calls[[2]]
## test_sq()
## 
## $sys.calls[[3]]
## test()
## 
## $sys.calls[[4]]
## sys.status()
## 
## 
## $sys.parents
## [1] 0 0 2 3
## 
## $sys.frames
## $sys.frames[[1]]
## <environment: 0x04766c60>
##   
##   $sys.frames[[2]]
## <environment: 0x04766dcc>
##   
##   $sys.frames[[3]]
## <environment: 0x04766e04>
##   
##   $sys.frames[[4]]
## <environment: 0x04766e3c>
##   
##   
##   $sys.calls
## $sys.calls[[1]]
## print(test_sq())
## 
## $sys.calls[[2]]
## test_sq()
## 
## $sys.calls[[3]]
## test()
## 
## $sys.calls[[4]]
## sys.status()
## 
## 
## $sys.parents
## [1] 0 0 2 3
## 
## $sys.frames
## $sys.frames[[1]]
## <environment: 0x04765ac8>
##   
##   $sys.frames[[2]]
## <environment: 0x04765c34>
##   
##   $sys.frames[[3]]
## <environment: 0x04765c6c>
##   
##   $sys.frames[[4]]
## <environment: 0x04765d30>

test_sq()


## $sys.calls
## $sys.calls[[1]]
## test_sq()
## 
## $sys.calls[[2]]
## test()
## 
## $sys.calls[[3]]
## sys.status()
## 
## 
## $sys.parents
## [1] 0 1 2
## 
## $sys.frames
## $sys.frames[[1]]
## <environment: 0x0475ce40>
##   
##   $sys.frames[[2]]
## <environment: 0x0475cee8>
##   
##   $sys.frames[[3]]
## <environment: 0x0475cf20>

答案 1 :(得分:2)

不幸的是,for通常不会出现在sys.calls中。虽然它有点像黑客,你实际上可以覆盖for,导致它被包含在内:

`for` = function(iter, vec, expr) eval.parent(replace(sys.call(), 1, list(.Primitive('for'))))
in.for = function() '`for`' %in% lapply(sys.calls(), `[[`, 1)
my.fun = function() { print('before'); print(in.for()); print('after') }

my.fun()
# [1] "before"
# [1] FALSE
# [1] "after"
for (x in 1) my.fun()
# [1] "before"
# [1] TRUE
# [1] "after"

答案 2 :(得分:0)

为什么不直接使用可选参数

Blah <- function(Param1, OptionalParam = 0){
    if(OptionalParam == 1){
        #Do This
    }else{
        #Do this
    }
    #Everything Else
}

答案 3 :(得分:0)

哎呀,那是不成熟的。事实证明,在for()循环后,索引变量 仍然存在。织补。

<击>哼!我可能有它。我已经有一个函数用一个变量的内容替换函数中的任意字符串:

replaceincall <- function(xx,from,to){
  # from is a string, to is a name
  if(is.name(xx)){
    ifelse(as.character(xx)==from,return(to),return(xx));
  } else {
    if(is.call(xx)) {
      oo <- lapply(as.list(xx),function(yy) replaceincall(yy,from,to));
      return(as.call(oo));
    } else {
      return(xx);
    }
  }
}

在我的重载<<-函数中,我还提取了sys.call()中与函数不对应的名称列表。这意味着它们是某种变量。 我所要做的就是找到那些不在ls(.GlobalEnv)中的那些,那些必须是索引变量的那些,并且应该用它们在日志条目中的值替换(使用上面的函数)

现在,这可能会捕获并替换除循环之外的东西...但也许这是一件好事,因为无论变量不在.GlobalEnv中的原因,它仍然是一个动态变量,因此有一天当我'我正在查看日志如果我现在没有捕获它的价值,我会想知道如何重建它。

有没有人在这个推理中看到任何缺陷?