2016-12-11 27 views
0

Rの中に、呼び出し元の呼び出し元のコンテキストから変数の名前を取得する関数を記述したいと思います。私が持っている問題は、deparsesubstituteをどのように構成するかを尋ねることによって最もよく理解されると思います。あなたは素朴な組成物は動作しないことがわかります。Rでは、 `deparse(substitute(x))`と同等の関数をどのように定義するのですか?

# a compose operator 
> `%c%` = function(x,y)function(...)x(y(...)) 

# a naive attempt to combine deparse and substitute 
> desub = deparse %c% substitute 
> f=function(foo) { message(desub(foo)) } 
> f(log) 
foo 

# this is how it is supposed to work 
> g=function(foo) { message(deparse(substitute(foo))) } 
> g(log) 
log 

私もeval.parentを含むバリエーションのカップルを試みたが、運と。どんな助けもありがとうございます。


明確化:私は、例えば、deparse(substitute(...))の同義語を探していませんよmatch.call()[[2]] - どのような私が探していることはfの定義は上記gと同じ答えを生成するよう

desub = function(foo) { 
    ... 
    # What goes here? 
} 

関数を定義する方法です。それは次のようになります。おそらく、

> f=function(foo) { message(desub(foo)) } 
> f(log) 
log 

match.callは、上記desubの体内での使用の可能性がありますが、私はどのように知っているように思います。ありがとう!

+0

あなたは – akrun

+0

@akrunをmatch.call' '確認することができます:私はmatch.call''について知っているが、私はそれが役立つかを見ていませんよ。あなたは少し詳しく説明しますか?あるいは、私が求めていることをするコード行を提供するのが最も簡単です。 – Metamorphic

+0

私は 'g1 < - function(foo)match。call()[[2]]; g1(ログ)#ログ ' – akrun

答えて

1

おかげで@ egnhaと@akrunは勇敢な試みをしています。ちょっと遊んだ後、私はうまくいく解決策を見つけました。

このフラグメント:

desub <- function(y) { 
    e1=substitute(y) 
    e2=do.call(substitute,list(e1), env=parent.frame()) 
    deparse(e2) 
} 

ができます:

> f <- function(x) message(desub(x)) 
> f(log) 
log 

を更新:

R-develのリスト上のマークBravingtonからの助けを借りて、私はこれを一般化することができました複数のフレームに分割する。私はここにそれを載せるべきだと思っていました。なぜなら、これは上記よりも少し便利だからです。そして、parent.frame()に(おそらくバグのような)振る舞いを伴う厄介な回避策があったからです。

# desub(v,0)=="v" 
# desub(v,1)==deparse(substitute(v)) 
# desub(v,2)==name of v in grandparent's frame 
# etc. 
desub = function(y,n=1) { 
    env=environment(); 
    for(i in 0:n) { 
    y = do.call(substitute, list(substitute(y)), env=env) 
    env = do.call(my_mvb_parent, list(), env=env) 
    } 
    deparse(y) 
} 

# helper: 
# 
# - using mvb.parent.frame fixes problems with capture.output and 
# weird cycling behavior in the built-in parent.frame 
# 
# - this wrapper makes mvb.parent.frame not throw an error when we get 
# to globalenv() 
my_mvb_parent=function() { 
    library(mvbutils) 
    tryCatch(
    mvb.parent.frame(2), 
    error=function(e) { globalenv()}) 
} 

if(1) { 
    # example code 
    g2=function(t) { 
    for(i in 0:5) { 
     res=desub(t,i); 
     print(res); 
     res1=capture.output(desub(t,i)) 
     stopifnot(capture.output(res)==res1) 
    } 
    } 
    g1=function(z) g2(z) 
    g=function(y) g1(y) 
    g(log) 
    # prints: 
    ## [1] "t" 
    ## [1] "z" 
    ## [1] "y" 
    ## [1] "log" 
    ## [1] "log" 
    ## [1] "log" 
} 
2

あなたが推測しているように、これは環境に関する問題です。 f(log)を呼び出すときに、関数flogを与えない理由は、が呼び出される環境、つまり評価環境がdesubであり、logへのバインディングを含まないということです。

救済が適切な環境でsubstituteへの呼び出しを評価し、それに応じてdesubを変更することです:

desub <- function(x, env = parent.frame()) { 
    deparse(eval(substitute(substitute(x)), envir = env)) 
} 

fは、それが行うことを意図していたものを行います。

f(log) 
#> log 
+0

egnha:ありがとうございます - 私がそれを受け入れる前に、あなたの答えを編集して "#ここに行くの?"というコードを入力してもらえますか? – Metamorphic

+0

また、あなたの答えは 'f_new'の' x'という引数に依存します。 'y'に変更すると、プログラムは' x'を出力します。 – Metamorphic

+0

@Metamorphicあなたは正しいです。その行動は、私が与えた推論と一致しています。それにもかかわらず、私のソリューションのバリエーションは、元の問題設定をより忠実に解決します。私は更新します。 – egnha

関連する問題