17

循環的複雑度は、関数を介して取得できる分岐の数を測定します。R関数について計算するための既存の関数/ツールはありますか?そうでない場合は、それを書くための最良の方法についての提案を歓迎します。

これに向けた安価なスタートは、、または関数内でのすべての発生をカウントするifことifelseですswitch。ただし、実際の答えを得るには、ブランチがいつ開始および終了するかを理解する必要がありますが、これははるかに困難です。たぶん、いくつかのR解析ツールが私たちを始めさせるでしょうか?

4

2 に答える 2

7

を使用codetools::walkCodeしてコード ツリーをたどることができます。残念ながら、codetools のドキュメントはかなりまばらです。ここでは、開始するための説明とサンプルを示します。

walkCode式とコード ウォーカーを取ります。コード ウォーカーは、ユーザーが作成するリストであり、3 つのコールバック関数 ( handlercall、および) を含める必要があります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 ステートメントの場合など)。ハンドラーが戻るとNULLcall通常どおり呼び出されます。代わりに関数を返す場合、それが関数の代わりに呼び出されます。

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
}
于 2011-08-18T23:44:35.803 に答える
4

また、cyclocomp (2016 年リリース) という新しいパッケージを見つけました。見てみな!

于 2016-05-24T22:03:00.830 に答える