首先,考虑以下计算函数被调用次数的Python代码:

def counter(fn):
    count = 0
    def inner(*args, **kwargs):
        nonlocal count
        count +=1
        print('Function {0} was called {1} times'.format(fn.__name__, count))
        return fn(*args, **kwargs)
    return inner

def add(a,b):
    return a+b
def mult(a,b):
    return a*b
add = counter(add)
mult = counter(mult)
add(1,2)
add(2,3)
mult(1,5)
#output
Function add was called 1 times
Function add was called 2 times
Function mult was called 1 times

现在,我正try 在R中执行相同的方法,如下所示:

counter <- function(fn) {
  cnt <- 0
  inner <- function(...) {
    cnt <<- cnt + 1
    print(paste("Function", match.call(), "was called", cnt, "times\n"))
    return(fn(...))
  }
  return(inner)
  
}
add <- function(a, b) a + b
mult <- function(a, b) a*b
cnt_add <- counter(add)
cnt_add(1, 4) 
cnt_add(3, 9)
[1] "Function cnt_add was called 1 times\n"
[2] "Function 1 was called 1 times\n"   #<---- !!!!!!!!!!!!!!  L1  
[3] "Function 4 was called 1 times\n"   #<---- !!!!!!!!!!!!!!  L2 
[1] 5
[1] "Function cnt_add was called 2 times\n"
[2] "Function 3 was called 2 times\n"   #<---- !!!!!!!!!!!!!!  L3 
[3] "Function 9 was called 2 times\n"   #<---- !!!!!!!!!!!!!!   
[1] 12
cnt_mult<-counter(mult)
cnt_mult(1,6) 
[1] "Function cnt_mult was called 1 times\n"
[2] "Function 1 was called 1 times\n"   #<---- !!!!!!!!!!!!!!  L4  
[3] "Function 6 was called 1 times\n"   #<---- !!!!!!!!!!!!!!  L5  
[1] 6

a)我以为"Function?Is Call?Times\n",但为什么打印L1、L2、L3、L4、L5?

当我try 时为b)(就像在Python中一样)

add <- counter(add)
add(3, 4)

我得到一个错误:Error: evaluation nested too deeply....

c)个 为了避免b中的错误,我try 了如下操作,但仍收到错误

cnt_add <- counter(add)
add <- cnt_add
add(6, 8)

我发现,如果我调用cnt_add函数一次,没有发生错误(除了控制台中的另外两行):

cnt_add <- counter(add)
cnt_add(1, 8)
[1] "Function cnt_add was called 1 times\n"
[2] "Function 1 was called 1 times\n"      
[3] "Function 8 was called 1 times\n"      
[1] 9
add <- cnt_add
add(6, 8)
[1] "Function add was called 2 times\n" "Function 6 was called 2 times\n"  
[3] "Function 8 was called 2 times\n"  
[1] 14

但是为什么"函数加被调用了2次",我就调用了一次!为什么它至少需要一次通话才能正常工作?

如何解决这些问题?我不想要其他方法,因为这只是闭包中的一种做法.

推荐答案

A)match.call提供了整个调用,而不仅仅是您调用的函数的名称.用match.call()[[1]]来实现这一点.但是deparse(substitute(fn))提供了您作为fn传递的字符串版本,所以它可能更好.(我的 Select 给出了原始函数名,而不是修改后的函数名.如果你想要修改后的版本,请坚持使用match.call()[[1]].)

B)你被懒惰的判断咬了一口.在你对counter的定义中给force(fn)打个电话.问题是,counter永远不会计算fn,所以它被留作promise ,直到你第一次呼叫add时需要它.但在这一点上,add的定义已经改变,所以你得到了无限循环.使用force(fn)会强制确定promise 的值.

counter<-function(fn){
  force(fn)
  name <- deparse(substitute(fn))
  cnt <- 0
  inner <- function(...){
    cnt <<- cnt+1
    print(paste("Function",name,"was called",cnt,"times\n"))
    return(fn(...))
  }
  return(inner)
  
}
add  <- function(a,b) a+b
mult <- function(a,b) a*b
add  <-counter(add)
add(1,4)
#> [1] "Function add was called 1 times\n"
#> [1] 5
add(3,9)
#> [1] "Function add was called 2 times\n"
#> [1] 12

创建于2022-09-25,共reprex v2.0.2

R相关问答推荐

是否有R函数来判断一个组中的所有值是否与另一个组中的所有值相同?

有没有方法将琴弦完全捕捉到R中的多边形?

在特定列上滞后n行,同时扩展框架的长度

单击 map 后,将坐标复制到剪贴板

根据R中的另一个日期从多列中 Select 最近的日期和相应的结果

多重RHS固定估计

用derrr在R中查找组间的重复项

如何从像glm这样的模型中提取系数表的相关性?

在数组索引上复制矩阵时出错

根据类别合并(汇总)某些行

使用`Watch()`和`renderUI()`时,不再满足仍出现在SHILINY AFTER条件中的条件输入

当我添加美学时,geom_point未对齐

R:用GGPLATE,如何在两个独立的变量中制作不同形状的散点图?

`夹心::vcovCL`不等于`AER::tobit`标准错误

WRS2包中带有bwtrim的简单ANOVA抛出错误

避免在图例中显示VLINS组

访问数据帧中未定义的列时出现R错误

整理ggmosaic图的标签

R中的Desolve:返回的导数数错误

带查找数据的FCT_REORDER.帧