1

R でフレームワークを開発中ですが、機能の 1 つを多目的にしたいと考えています。厳密に 1 つの引数セットを渡すように要求することで、これを実現したいと考えています。つまり、引数とORfoo引数のいずれかを必要とする関数を書きたいと思います。どちらのセットも指定されていない場合、セットが不完全な場合、または両方のセットが指定されている場合は、エラーがスローされます。xya

これを実現する 1 つの方法は、オプションの引数のみを使用し、その後にifステートメントを続けることです。これを以下に示します。しかし、私はこれをもっとエレガントにしたいと思っています。

foo <- function(x, y, a){
  if (!missing(a) & missing(x) & missing(y)){
    a
    return("Only a provided")
  } else if (missing(a) & !missing(x) & !missing(y)){
    x; y
    return("x and y provided")
  } else {
  stop("No complete and/or distinct argument set provided")
}

関数は次のように動作する必要があります。

> foo(a = 1)
[1] "Only a provided"

> foo(x = 1, y = 2)
[1] "x and y provided"

> foo()
Error in foo() : No complete and/or distinct argument set provided

> foo(x = 1)
Error in foo(x = 1) : No complete and/or distinct argument set provided

> foo(x = 1, y = 2, a = 3)
Error in foo(x = 1, y = 2, a = 3) : 
  No complete and/or distinct argument set provided

任意のサイズの任意の数の引数セットを処理できる一般化された回答も含めることに対する追加のクレジット。

余談: 上記の例ではmissing()引数のデフォルトを使用せず、引数を使用していませんが、これは決して要件ではありません。目前の質問に対する適切な解決策を提供する限り、さまざまな形式を柔軟に使用できます。

4

2 に答える 2

1

@r2evans によって示されたアプローチの別のオプションは、...ディスパッチに使用することです。

foo <- function(...) {
    args <- list(...)
    if("a" %in% names(args) && "x" %in% names(args) && y %in% names(args))
        stop("need either 'a' or 'x' and 'y' arguments.")
    if("a" %in% names(args)) return(foo_a(a=args[["a"]]))
    if("x" %in% names(args) && "y" %in% names(args)) return(foo_xy(x=args[["x"]], y=args[["y"]])
    stop("need either 'a' or 'x' and 'y' arguments.")
}

実際の計算を定義foo_aして実行する必要があります。foo_xyこのアプローチの欠点は、名前付き引数でしか機能しないことです。foo(2,3)の代わりに を呼び出すとfoo(x=2, y=3)、エラーが発生します。これは、上記のコードの長さを見れば解決できますがargs、処理するパラメータが増えるとすぐに厄介になります。

さらに別のオプションは、引数セットを (S3 または S4) オブジェクトに収集し、このように引数セット クラスでディスパッチすることです。

xy_arg <- function(x,y) {
    ans <- list(x=x, y=y)
    class(ans) <- "xy_arg"
    return(ans)
}
a_arg - function(a) {
    ans <- list(a=a)
    class(ans) <- "a_arg"
    return(ans)
}
foo <- function(x, ...) UseMethod("foo", x)
foo.xy_arg <- function(x, ...) { 
    #compute for argument set where x and y is given
    print(x[["x"]], x[["y"]])
}
foo.a_arg <- function(x, ...) 
    print(x[["a"]])
}
foo(xy_arg(x=1, y=2))
foo(a_arg(a=3))

これは最初はより複雑に見えますが、体系的な方法でより多くの引数セットを定義できます。`

foo1 つのパラメータ セットのみで動作するように定義し、正規化されたインターフェイス オブジェクトを使用xy_argして構築することも考えられa_argます。つまり、(x,y) または (a) から標準問題への問題変換を実行します。

于 2017-10-16T09:11:14.307 に答える