6

存在しない変数を関数に渡してしまうというかなり複雑な状況があります。これがいつ発生するかはよくわかっていますが、修正するのは難しいでしょう。状態を確実に検出でき、その場合の回避策を実行できれば満足です。私は単に使用することができます

inherits(try(eval(possibly_missing_variable),silent=TRUE),"try-error")

しかし、可能であれば、エラーにつながる特定の条件をテストしたいと思いますobject 'possibly_missing_variable' not found。(エラー メッセージの "not found" を grep しようとすることもできますが、過去に r-devel リストで、R が別の言語で実行されている場合、これは失敗するので、翻訳されたバージョンのエラーメッセージが表示されます。)

のさまざまな組み合わせを試しましdeparse(substitute(...))たが、コール スタックで十分に実行されていないようです。再現可能な例での私のベストショットは次のとおりです。

f <- function(d) {
    ## test here
    cat("'d' exists:",exists("d"),"\n") ## TRUE
    cat("deparse(substitute(d)):",dd <- deparse(substitute(d)),"\n") ## OK
    cat("exists('",dd,"'): ",exists(dd),"\n",sep="")
    eval(d)
}

f2 <- function(ddd) {
    f(ddd)
}

ddd <- 5
f2(junk)

結果は次のとおりです。

'd' exists: TRUE 
deparse(substitute(d)): ddd 
exists('ddd'): TRUE
Error in eval(d) : object 'junk' not found

関連するオブジェクトが環境のスタック/囲んでいる環境などのどこにも見つからないため、評価が失敗することを (エラーが発生する前に) 正しく通知するテストが必要です。

より一般的には、引数の最も上流の名前を把握する方法はありますか ("junk"この場合)? それができればexists(farthest_upstream_name)、私の問題は解決します。

4

2 に答える 2

5

おそらくこのようなものです(この質問に対する私の2番目の回答から盗まれました)?

f <- function(d) {
    ## test here
    ff <- sys.frames()
    ex <- substitute(d)
    ii <- rev(seq_along(ff))
    for(i in ii) {
        ex <- eval(substitute(substitute(x, env=sys.frames()[[n]]),
                              env = list(x = ex, n=i)))
    }
    if(!exists(deparse(ex))) stop("Substitute real error action here")
    eval(d)
}

f2 <- function(ddd) {
    f(ddd)
}

ddd <- 5
f2(junk)
## Error in f(ddd) (from #10) : Substitute real error action here
于 2013-02-18T21:31:57.637 に答える
3

Josh O'Brien のアプローチが好きです。ただし、fそこで定義されているように使用すると、渡された名前が実際にアクティブなバインディングを持っている場合でも、(グローバル環境ではなく) コール スタック内の関数に対してローカルに作成された場合でも、「存在しない」エラー状態がトリガーされる可能性があります。 )。また、Ben の意図した使用法とは特に関係がないかもしれませんが、引数が単なる名前ではなく式である場合、エラーが発生します。

簡単な修正は、Josh の関数を微調整してis.symbolテストを含めることです。

f <- function(d) {
    ## test here
    ff <- sys.frames()
    ex <- substitute(d)
    ii <- rev(seq_along(ff))
    for(i in ii) {
        ex <- eval(substitute(substitute(x, env=sys.frames()[[n]]),
                              env = list(x = ex, n=i)))
    }
    if(is.symbol(ex) && !exists(deparse(ex))) {
        stop("Substitute real error action here")
    }
    eval(d)
}

目的のチェックは引き続き機能します。

f2 <- function(ddd) {
    f(ddd)
}
f2(junk)
## Error in f(ddd) : Substitute real error action here

ただし、次の 2 つのケースは、エラーが発生するのではなく、通過するようになりました。

# case 1: argument to f is local to a calling function
f3 <- function() {
    notjunk <- 999
    f(notjunk)
}
f3()
## [1] 999

# case 2: argument to f is an expression
f2(5+5)
## [1] 10

で何が起こっているかとfいうと、call-substitute-substitute を繰り返し適用した後、ex上記のケース 1 では評価された引数自体に設定され、ケース 2 では渡された (まだ評価されていない) 呼び出しに設定されます。どちらの場合も、existsテストだけではは実際には名前 (別名シンボル) ではないため失敗exしますが、名前を超えて解決できた場合、明らかに存在しないことは問題ではありません。

于 2013-02-22T09:48:53.577 に答える