你如何计算R函数的圈复杂度?

时间:2011-08-12 13:58:22

标签: r complexity-theory cyclomatic-complexity

Cyclomatic complexity测量可以通过函数获取多少个可能的分支。是否有现有的函数/工具来计算R函数?如果没有,建议是最好的方式来写一个。

一个便宜的开始就是计算你职能中ififelseswitch的所有出现次数。要获得真正的答案,您需要了解分支何时开始和结束,这要困难得多。也许一些R解析工具会让我们开始?

2 个答案:

答案 0 :(得分:7)

您可以使用codetools::walkCode遍历代码树。不幸的是,codetools的文档非常稀少。这是一个解释和示例,以帮助您入门。

walkCode采用表达式和代码walker。代码walker是您创建的列表,必须包含三个回调函数:handlercallleaf。 (您可以使用辅助函数makeCodeWalker为每个函数提供合理的默认实现。)walkCode遍历代码树并调用代码遍历器。

遇到复合表达式时会调用

call(e, w)e是表达式,w是代码walker本身。默认实现只是简单地递归到表达式的子节点(for (ee in as.list(e)) if (!missing(ee)) walkCode(ee, w))。

遇到树中的叶节点时,将调用

leaf(e, w)。同样,e是叶节点表达式,w是代码walker。默认实现只是print(e)

为每个复合表达式调用

handler(v, w),可以使用它为call的某些类型的表达式轻松提供替代行为。 v是复合表达式的父级的字符串表示形式(有点难以解释 - 但如果它是赋值表达式,则基本上是<-{如果它是块的开头,if如果是if语句,等等。如果处理程序返回NULL,则照常调用call;如果你返回一个函数,那就是调用函数而不是函数。

这是一个非常简单的示例,用于计算函数的ififelse的出现次数。希望这至少可以让你开始!

library(codetools)

countBranches <- function(func) {
  count <- 0
  walkCode(body(func), 
           makeCodeWalker(
             handler=function(v, w) {
               if (v == 'if' || v == 'ifelse')
                 count <<- count + 1
               NULL  # allow normal recursion
             },
             leaf=function(e, w) NULL))
  count
}

答案 1 :(得分:2)

另外,我刚刚发现了一个名为cyclocomp的新软件包(2016年发布)。看看吧!