4

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

これは私がどこまで進んだかです、そして私はこのアプローチがうまくいかないことに気づきました...

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

ありがとう!

4

3 に答える 3

8

以下は、関数引数の遅延評価を維持しながら、適度にきれいに出力する関数を構築する Curry のバージョンです。

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
}

基本的には、部分バインディングを自分で構築する場合とまったく同じ方法で無名関数を生成することによって機能します。

于 2011-07-04T01:31:43.987 に答える
5

実際、これは回避策として機能するようです

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

ただし、理想的には、バインドされた引数が新しい関数から完全に消えて、新しい関数の呼び出しが名前指定で発生できるようにする必要があります。たとえば、3 を返しadd <- function(a,b) a+bたいとします。(bind(add,a=2))(1)

于 2011-07-01T11:22:51.410 に答える
4

roxygen の 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

編集: Curry は、名前付きまたは名前なしの引数を受け入れるように簡潔に定義されていますが、割り当てfunによる引数への部分的な適用にはformal()、同じ機能をエミュレートするためのより洗練されたマッチングが必要です。例えば:

> 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 番目の引数として渡す必要があります。2b=

> oneplusb
function (a = 1, b) 
{
    a + 2 * b
}
> oneplusb(b=2) ## or oneplusb(,2)
[1] 5
于 2011-07-01T11:22:18.333 に答える