2011-07-01 32 views
4

Rの関数に引数を部分的にバインド/適用するにはどうすればよいですか? ...関数引数をバインドする方法

bind <- function(fun,...) 
{ 
    argNames <- names(formals(fun)) 
    bindedArgs <- list(...) 
    bindedNames <- names(bindedArgs) 
    function(argNames[!argNames %in% bindedArgs]) 
    { 
    #TODO 
    } 
} 

おかげ

これは、私が得たどのくらいですし、私は、このアプローチは動作しないことに気づきました!

+0

あなたは何をしようとしていますか?コール関数は、それが正式な引数で 'fun'として渡されましたか?もしそうなら、「楽しい」にも「...」があるとしたら? –

+0

bunction引数を見つける方法 – mdsumner

答えて

4

roxygen's Curry関数を見てみましたか?

> library(roxygen) 
> Curry 
function (FUN, ...) 
{ 
    .orig = list(...) 
    function(...) do.call(FUN, c(.orig, list(...))) 
} 
<environment: namespace:roxygen> 

使用例:

> aplusb <- function(a,b) { 
+ a + 2*b 
+ } 
> oneplusb <- Curry(aplusb,1) 
> oneplusb(2) 
[1] 5 

編集: カレーを簡潔に名前付きまたは名前なし引数を受け入れるように定義されていますが、formal()譲渡の方法によって、引数にfunの部分的なアプリケーションがに、より洗練されたマッチングを必要としています同じ機能をエミュレートします。例えば:

> bind <- function(fun,...) 
+ { 
+ argNames <- names(formals(fun)) 
+ boundArgs <- list(...) 
+ boundNames <- names(boundArgs) 
+ if(is.null(boundNames)) { 
+  formals(fun)[1:length(boundArgs)] <- boundArgs 
+ } else { 
+  formals(fun)[match(names(boundArgs),argNames)] <- boundArgs 
+ } 
+ fun 
+ } 
> oneplusb <- bind(aplusb,1) 
> oneplusb(2) 
Error in 2 * b : 'b' is missing 

この関数の最初の引数はまだaですので、あなたは2が(b=)のために意図されている引数を指定、または2番目の引数として渡しする必要があります。

> oneplusb 
function (a = 1, b) 
{ 
    a + 2 * b 
} 
> oneplusb(b=2) ## or oneplusb(,2) 
[1] 5 
+0

いいえ、私はポインタのおかげでいませんでした。 'function(FUN、...) { .orig = list(...) 関数(...)do.call(FUN、c(.orig、list(...))) } ' 本当に単純な解決策です...しかし、これは結果関数から名前を完全に削除します...しかし、それ以上の解決策では両方のケースをカバーすることができます。 – Cookie

+0

実際には、引き続き引数を 'Curry'に渡すことができます。' Curry(aplusb、b = 2)(a = 1) '。 – hatmatrix

+0

あなたは正しいです、カレーは必要に応じて正確に働いています! – Cookie

4

実は、これはしかし、理想的に私は新しい関数の呼び出しは、名前で起こることができるようにバインドされた引数は、新たな機能から完全に消失したい

bind <- function(fun,...) 
{ 
    boundArgs <- list(...) 
    formals(fun)[names(boundArgs)] <- boundArgs 
    fun 
} 

周りの仕事として動作しているようです仕様、例えばadd <- function(a,b) a+bと私はここで

+0

これは正式なマッチングよりも優れています。 – hatmatrix

7

3.両方が関数の引数の遅延評価を維持することをカレーのバージョンだ返すように(bind(add,a=2))(1)を好きですが、機能を構築することを適度にうまくプリント:それは基本的に発生させることにより動作します

Curry <- function(FUN, ...) { 
    args <- match.call(expand.dots = FALSE)$... 
    args$... <- as.name("...") 

    env <- new.env(parent = parent.frame()) 

    if (is.name(FUN)) { 
    fname <- FUN 
    } else if (is.character(FUN)) { 
    fname <- as.name(FUN) 
    } else if (is.function(FUN)){ 
    fname <- as.name("FUN") 
    env$FUN <- FUN 
    } else { 
    stop("FUN not function or name of function") 
    } 
    curry_call <- as.call(c(list(fname), args)) 

    f <- eval(call("function", as.pairlist(alist(... =)), curry_call)) 
    environment(f) <- env 
    f 
} 

あなた自身が部分的なバインディングを構築していた場合とまったく同じ方法で、無名関数を呼び出すことができます。

+0

乾杯、ありがとう、素敵な解決策! – Cookie

+0

これはいつでもプライヤーで見ることができますか? Rコアはカレーが好きではないように見えますが、ロキシゲンは不便な場所です。 – baptiste

+0

いいえ、高次関数パッケージに表示されることがあります。 – hadley

関連する問題