7

ネストされた関数呼び出しと引数評価の操作方法を理解するのに苦労しています。

簡単な例を次に示します。topfunction1 つの数値引数を持つトップレベル関数があります。の中で、引数が の中で定義された関数への呼び出しであるtopfunction別の関数を呼び出します。lowerfunctionlowerfunction

topfunction<-function(x){  
  lowerfunction(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3]))
}

lowerfunction<-function(mycall){ 

  myfun<-function(first,second=0,third=NULL){
    print(first)
    print(second)
    print(third)
  }

  mc<-match.call(definition = myfun, call = match.call()[[2]]) 
  eval(mc) 
}

内部でlowerfunctionは、関数呼び出しを でキャプチャし、呼び出しmatch.callを評価しようとします。しかし、 variablexは の環境でのみ定義されているためtopfunction、評価は失敗します。

topfunction(x=1:3)
Error in print(first) : object 'x' not found

私はラインを変更できることを知っています

lowerfunction(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3]))

なので

lowerfunction(substitute(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3])))

topfunction、しかし私の実際のアプリケーションでtopfunctionは はユーザーによって構築されるため、解決策はレベルlowerfunctionまたはmyfunレベルで何らかの形で発生するはずです。しかし、彼らはすでに に関する情報を失っているのでx、それが達成できるかどうかわかりませんか?

実際のアプリケーションでは、topfunctionは を使用してモデルを構築し、lowerfunctionその可能性を計算しますが、 の引数lowerfunctionは、 を介して評価される関数呼び出しを含むことができる式evalです。これらの関数は、 内でのみ定義されますlowerfunction。また、lowerfunction直接呼び出すこともできます。

x<-1:3
lowerfunction(myfun(first=x[1],second=x[2],third=if(length(x)>2) x[3]))
# or
lowerfunction(myfun(first=x1,second=2)

したがってx、の引数リストに追加するソリューションlowerfunctionは、一般的に適用できません。

したがって、問題は、ある環境 (パッケージ名前空間、またはこの場合は の環境) からevalの定義を取得し、他の環境、つまり の環境での引数を評価する必要があることです。myfunlowerfunctionmyfuntopfunction

4

2 に答える 2

3

以下のように呼び出しを持ち上げmyfunlowerfun変更します。evalパッケージを作成するとき、エクスポートmyfunしないと、 から直接アクセスできなくなりますR_GlobalEnvが、 内から呼び出すことはできますlowerfun

topfunction <- function(x){  
    lowerfunction(myfun(first=x[1], second=x[2], third=if(length(x)>2) x[3]))
}
lowerfunction<-function(mycall){
    mc <- match.call(definition = myfun, call = match.call()[[2]]) 
    eval(mc, envir=parent.frame()) 
}
myfun <- function(first, second=0, third=NULL){
    print(first)
    print(second)
    print(third)
}

実行例:

> topfunction(1:3)
[1] 1
[1] 2
[1] 3

トピック外: を呼び出すmyfunことで引き続きアクセスできますR_GlobalEnv

getFromNamespace("myfun", "mypackage")

アップデート

概念的なポイントを保持するために本当にmyfun内に保持したい場合は、 との環境をマージしてそこで評価する必要がありますが、それが可能かどうかはわかりません (@hadley の回答を参照してください)。lowerfunctiontopfunctionlowerfunctionmc

lowerfunctionただし、 の環境で見つからない変数(つまり x、 ) はtopfunction、評価の前に の環境からコピーできます。遅延評価のおかげで、変更されない限り、これはメモリ使用量に影響しません。

lowerfunction<-function(mycall){
    myfun <- function(first, second=0, third=NULL){
        print(first)
        print(second)
        print(third)
    }
    mc <- match.call(definition = myfun, call = match.call()[[2]]) 
    x <- get("x", parent.frame())
    eval(mc)
}

ただし、ユーザーが に組み込むオブジェクトがわからないためtopfunction、上記のようにハード コードすることはできませんが、からすべての名前mcを抽出してコピーする必要がありますassign。可能ですが、手間を省いて と の両方lowerfunctionをエクスポートすることをお勧めしますmyfun

于 2013-09-03T08:10:59.077 に答える