私は、引数として渡されたオブジェクトをその場で変更するという非 R 標準の慣行に従う多くの関数を持つ R パッケージに取り組んでいます。これは通常は問題なく機能しますが、変更するオブジェクトがリストにある場合は失敗します。
割り当ての形式の例を示す関数:
myFun<-function(x){
xn <- deparse(substitute(x))
ev <- parent.frame()
# would do real stuff here ..
# instead set simple value to modify local copy
x[[1]]<-"b"
# assign in parent frame
if (exists(xn, envir = ev))
on.exit(assign(xn, x, pos = ev))
# return invisibly
invisible(x)
}
これは機能します:
> myObj <-list("a")
> myFun(myObj)
> myObj
[[1]]
[1] "b"
ただし、オブジェクトがリストのメンバーである場合は機能しません。
> myObj <-list("a")
> myList<-list(myObj,myObj)
> myFun(myList[[1]])
> myList
[[1]]
[[1]][[1]]
[1] "a"
[[2]]
[[2]][[1]]
[1] "a"
ここで他の質問への回答を読んだ後、assign
明確な状態のドキュメントが表示されます。
assign does not dispatch assignment methods, so it cannot be used to set elements of vectors, names, attributes, etc.
これらの関数を使用する既存のコードベースがあるため、modify-in-place 構文を放棄することはできません。親フレームのリストのメンバーであるオブジェクトを変更するための回避策または代替アプローチについて提案がある人はいますか?
アップデート:
次のような独自の代入関数をロールしようと考えました。
assignToListInEnv<-function(name,env,value){
# assume name is something like "myList[[1]]"
#check for brackets
index<-regexpr('[[',name,fixed=TRUE)[1]
if(index>0){
lname<-substr(name,0,index-1)
#check that it exists
if (exists(lname,where=env)){
target<-get(lname,pos=env)
# make sure it is a list
if (is.list(target)){
eval(parse(text=paste('target',substr(name,index,999),'<-value',sep='')))
assign(lname, target, pos = env)
} else {
stop('object ',lname,' is not a list in environment ',env)
}
} else {
stop('unable to locate object ',lname,' in frame ',env)
}
}
}
しかし、それはひどくもろく、さらに多くのケースを処理する必要があり ($
と[
同様に) 、間違ったフレームで評価される ため、[[
おそらくまだ失敗するでしょう...[[x]]
x