11

そのため、説明属性を追加するために、また S3 ジェネリックを使用してすべてを処理するために、R で構築しているいくつかの関数のクラスを変更しています。基本的に、私は次のような構造を持っています

foo <- function(x) x + 1

addFunction <- function(f, description) {
    class(f) <- c("addFunction", "function")
    attr(f, "description") <- description
    f
}

foo <- addFunction(foo, "Add one")

そして、私は次のようなことをします

description <- function(x) UseMethod("description")
description.default <- function(x) deparse(substitute(x))
description.addFunction <- function(x) attr(x, "description")

これは問題なく動作しますが、それほどエレガントではありません。このクラスのインスタンスを構文に似た構文で定義できるように、関数の新しいクラスを定義できるかどうか疑問に思っていfunctionます。つまり、次のように生成されるものを定義することはaddFunction可能ですか。foo

foo <- addFunction(description = "Add one", x) {
    x + 1
}

(または同様のもの、属性を関数に追加する必要がある場所について強い感情はありません)?

読んでくれてありがとう!


更新:私はこのアイデアをもう少し実験しましたが、まだ具体的な結果には達していません.

-関数をコピーしfunction()て別の名前を付け、後で操作するというアイデアを試しました。ただし、これは機能しません。ここで何が起こっているかについての情報があれば幸いです。

> function2 <- `function`
> identical(`function`, function2)
[1] TRUE
> function(x) x
function(x) x
> function2(x) x
Error: unexpected symbol in "function2(x) x"
> function2(x)
Error: incorrect number of arguments to "function"

function()プリミティブ関数であるため、より多くの手がかりを得るために、それを定義する C コードを調べてみました。function2(x)私は特に、呼び出しからのエラー メッセージに興味をそそられました。基礎となるCコードfunction()

/* Declared with a variable number of args in names.c */
  SEXP attribute_hidden do_function(SEXP call, SEXP op, SEXP args, SEXP rho)
{
  SEXP rval, srcref;

  if (TYPEOF(op) == PROMSXP) {
    op = forcePromise(op);
    SET_NAMED(op, 2);
  }
  if (length(args) < 2) WrongArgCount("function");
  CheckFormals(CAR(args));
  rval = mkCLOSXP(CAR(args), CADR(args), rho);
  srcref = CADDR(args);
  if (!isNull(srcref)) setAttrib(rval, R_SrcrefSymbol, srcref);
  return rval;
  }

callこのことから、何らかの理由で、 、opargsおよびの 4 つの引数のうち少なくとも 2 つrhoが現在必要であると結論付けています。の署名から、渡される 4 つの引数は、呼び出し、約束、引数のリスト、そしておそらく環境であるとdo_function()推測しています。do_function(これらの引数を 2 つまで NULL に設定するなど)についてさまざまな組み合わせを試しましたがfunction2、同じ (新しい) エラー メッセージが引き続き表示されます。

> function2(call("sum", 2, 1), NULL, list(x=NULL), baseenv())
Error: invalid formal argument list for "function"
> function2(call("sum", 2, 1), NULL, list(x=NULL), NULL)
Error: invalid formal argument list for "function"

CheckFormals()このエラー メッセージは、私も調べたC 関数から返されます。

/* used in coerce.c */
  void attribute_hidden CheckFormals(SEXP ls)
{
  if (isList(ls)) {
    for (; ls != R_NilValue; ls = CDR(ls))
      if (TYPEOF(TAG(ls)) != SYMSXP)
        goto err;
    return;
  }
  err:
    error(_("invalid formal argument list for \"function\""));
  }

私は C にまったく堪能ではないので、ここから先、次に何をすべきかよくわかりません。

だから、これらは私の更新された質問です:

  • 同じように振る舞うのとそうfunctionでないのはなぜですか?R で同一と見なされるのに、function2なぜ別の構文を使用して呼び出す必要があるのですか?function2
  • 実際に関数を定義するfunction2 ような適切な引数は何ですか?function2([arguments])
4

1 に答える 1