6

任意の正当な R 式で使用されているすべての関数の名前を見つけようとしていますが、以下の例を名前ではなく関数としてフラグ付けする関数が見つかりません。

test <- expression(
    this_is_a_function <- function(var1, var2){

    this_is_a_function(var1-1, var2)
})

all.vars(test, functions = FALSE)

[1] "this_is_a_function" "var1"              "var2" 

all.vars(expr, functions = FALSE) は、式で関数宣言 (f <- function(){}) を返し、関数呼び出し ('+'(1,2), ...) を除外しているようです。

名前ではなく関数として 'this_is_a_function' にフラグを立てる関数 (コア ライブラリまたは他の場所) はありますか? 構文的には正しいが、正しく評価されない可能性がある任意の式で動作する必要がある (例: '+'(1, 'duck'))

同様の質問を見つけましたが、解決策が含まれていないようです。

明確化が必要な場合は、下にコメントを残してください。パーサー パッケージを使用して式を解析しています。

編集:@ハドリー

スクリプト全体を含む式があります。これは通常、ネストされた関数定義を含むメイン関数で構成され、スクリプトの最後にメイン関数が呼び出されます。

関数はすべて式の中で定義されており、'<-' と '{' を含める必要があるかどうかは気にしません。これらは自分で簡単に除外できるからです。

動機は、すべての R スクリプトを取得し、関数の使用が時間の経過とともにどのように変化したかについての基本的な統計を収集することです。

編集:現在のソリューション

正規表現ベースのアプローチは、関数定義を取得し、James のコメントのメソッドと組み合わせて関数呼び出しを取得します。私は右側の割り当てを使用しないため、通常は機能します。

function_usage <- function(code_string){
    # takes a script, extracts function definitions

    require(stringr)

    code_string <- str_replace(code_string, 'expression\\(', '')

    equal_assign <- '.+[ \n]+<-[ \n]+function'
    arrow_assign <- '.+[ \n]+=[ \n]+function'

    function_names <- sapply(
        strsplit(
            str_match(code_string, equal_assign), split = '[ \n]+<-'),    
        function(x) x[1])

    function_names <- c(function_names, sapply(
        strsplit(
            str_match(code_string, arrow_assign), split = '[ \n]+='),    
            function(x) x[1]))

        return(table(function_names))    
    }
4

2 に答える 2

4

簡単な答え: is.function変数が実際に関数を保持しているかどうかを確認します。これらは呼び出しであるため、これは(評価されていない)呼び出しでは機能しません。また、マスキングにも注意する必要があります。

mean <- mean (x)

長い答え:

私見では、の2つの出現には大きな違いがありthis_is_a_functionます。

this_is_a_function 最初のケースでは、式を評価したら、名前を使用して変数に関数を割り当てます。2+2違いはとの間と同じ違い4です。
ただし、検索するだけ<- function ()では、結果が関数であることを保証するものではありません。

f <- function (x) {x + 1} (2)

2番目のオカレンスは、構文的には関数呼び出しです。this_is_a_function式から、呼び出しを適切に評価するために、関数を保持する呼び出された変数が存在する必要があることを判別できます。しかし、それがそのステートメントだけから存在するかどうかはわかりません。ただし、そのような変数が存在するかどうか、およびそれが関数であるかどうかを確認できます。

関数が他のタイプのデータと同様に変数に格納されるという事実は、最初のケースでは、の結果function ()が関数になることを知ることができ、この式が評価された直後に、名前を持つ変数this_is_a_functionが保持されると結論付けることを意味します機能。

ただし、Rには名前と関数がたくさんあります。「->」は代入関数(代入関数を保持する変数)の名前です...

式を評価した後、これを確認できますis.function (this_is_a_function)。ただし、これが関数を返す唯一の式ではありません。

f <- function () {g <- function (){}}
> body (f)[[2]][[3]]
function() {
}
> class (body (f)[[2]][[3]])
[1] "call"
> class (eval (body (f)[[2]][[3]]))
[1] "function"

all.vars(expr、functions = FALSE)は、関数呼び出し('+'(1,2)、...)を除外しながら、式で関数宣言(f <-function(){})を返すようです。

それは逆だと思います。その式fでは、関数が割り当てられる変数(名前)です(呼び出しが評価されると)。+(1、2)は数値に評価されます。あなたがそうしないようにしない限り。

e <- expression (1 + 2)
> e <- expression (1 + 2)
> e [[1]]
1 + 2
> e [[1]][[1]]
`+`
> class (e [[1]][[1]])
[1] "name"
> eval (e [[1]][[1]])
function (e1, e2)  .Primitive("+")
> class (eval (e [[1]][[1]]))
[1] "function"
于 2013-01-11T16:19:30.717 に答える
3

実際に関数を評価しないと正確に行うことが事実上不可能になる関数定義を探す代わりに、関数呼び出しを探す方が簡単です。

次の関数は、関数のように呼び出されるすべてのオブジェクトの名前を返す式/呼び出しツリーを再帰的にスパイダーします。

find_calls <- function(x) {
  # Base case
  if (!is.recursive(x)) return()

  recurse <- function(x) {
    sort(unique(as.character(unlist(lapply(x, find_calls)))))
  }

  if (is.call(x)) {
    f_name <- as.character(x[[1]])
    c(f_name, recurse(x[-1]))
  } else {
    recurse(x)
  }
}

単純なテスト ケースでは期待どおりに動作します。

x <- expression({
  f(3, g())
  h <- function(x, y) {
    i()
    j()
    k(l())
  }
})
find_calls(x)
# [1] "{"        "<-"       "f"        "function" "g"        "i"        "j"  
# [8] "k"        "l"       
于 2013-01-12T17:05:33.557 に答える