循環的複雑度は、関数を介して取得できる分岐の数を測定します。R関数について計算するための既存の関数/ツールはありますか?そうでない場合は、それを書くための最良の方法についての提案を歓迎します。
これに向けた安価なスタートは、、または関数内でのすべての発生をカウントするif
ことifelse
ですswitch
。ただし、実際の答えを得るには、ブランチがいつ開始および終了するかを理解する必要がありますが、これははるかに困難です。たぶん、いくつかのR解析ツールが私たちを始めさせるでしょうか?
循環的複雑度は、関数を介して取得できる分岐の数を測定します。R関数について計算するための既存の関数/ツールはありますか?そうでない場合は、それを書くための最良の方法についての提案を歓迎します。
これに向けた安価なスタートは、、または関数内でのすべての発生をカウントするif
ことifelse
ですswitch
。ただし、実際の答えを得るには、ブランチがいつ開始および終了するかを理解する必要がありますが、これははるかに困難です。たぶん、いくつかのR解析ツールが私たちを始めさせるでしょうか?
を使用codetools::walkCode
してコード ツリーをたどることができます。残念ながら、codetools のドキュメントはかなりまばらです。ここでは、開始するための説明とサンプルを示します。
walkCode
式とコード ウォーカーを取ります。コード ウォーカーは、ユーザーが作成するリストであり、3 つのコールバック関数 ( handler
、call
、および) を含める必要がありますleaf
。(ヘルパー関数makeCodeWalker
を使用して、それぞれの適切な既定の実装を提供できます。)walkCode
コード ツリーをウォークスルーし、コード ウォーカーを呼び出します。
call(e, w)
複合式に遭遇したときに呼び出されます。e
は式でw
あり、コード ウォーカーそのものです。デフォルトの実装は、単純に式の子ノード ( for (ee in as.list(e)) if (!missing(ee)) walkCode(ee, w)
) に再帰します。
leaf(e, w)
ツリー内のリーフ ノードに遭遇したときに呼び出されます。繰り返しますが、e
はリーフ ノード式で、w
はコード ウォーカーです。デフォルトの実装は単純print(e)
です。
handler(v, w)
は複合式ごとに呼び出されcall
、特定のタイプの式に対して代替動作を簡単に提供するために使用できます。v
複合式の親の文字列表現です (説明するのは少し難しいですが、基本的に<-
は代入式の{
場合、ブロックの開始のif
場合、if ステートメントの場合など)。ハンドラーが戻るとNULL
、call
通常どおり呼び出されます。代わりに関数を返す場合、それが関数の代わりに呼び出されます。
if
以下は、およびifelse
関数の出現回数をカウントする非常に単純な例です。うまくいけば、これで少なくとも始めることができます!
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
}
また、cyclocomp (2016 年リリース) という新しいパッケージを見つけました。見てみな!