2017-01-10 5 views
0

私のグローバル環境変数はmyListです。私はmyListを変更し、それをmyFunctionというグローバル環境に再割り当てする関数を持っています。 myListmyFunctionで変更したいだけです。他の機能がmyListを変更しないようにする方法はありますか?オブジェクトを変更できる関数を制限する

バックグラウンドでは、私はRユーザーのための一般的なツールを構築しています。私はツールのユーザーがmyListを変更する独自の関数を定義できるようにしたくありません。私は将来自分が書くかもしれない機能でmyListを修正できるように自分自身に望みません。

私は潜在的な解決策を持っていますが、私はそれが気に入らないのです。ツールが実行されると、ユーザーが定義したすべての関数のテキストを調べて、myListというテキストをグローバル環境に割り当てるテキストを検索できます。私はすべての機能を検索する必要があるという事実は好きではありません。

私が探しているものがRで実装可能かどうか知っていますか?ご提供いただけるお手伝いをありがとうございます。

再現可能な例として、次の例を可能にするコードが必要です。

assign('myList', list(), envir = globalenv()) 
myFunction <- function() { 
    myList <- c(myList, 'test') 
    assign('myList', myList, envir = globalenv()) 
} 
userFunction <- function() { 
    myList <- c(myList, 'test') 
    assign('myList', myList, envir = globalenv()) 
} 
myFunction() # I need some code that will allow this function to run successfully 
userFunction() # and cause an error when this function runs 
+0

あなたはS3クラスを見てください。そのクラスに固有のデータ構造とメソッドをほとんど持っているのが最適な解決策になるでしょう。あなたのデータは関数によって作成されたものではなく変更されているので、最初の入力は常に自由に実行できます。 – zacdav

答えて

1

modulesパッケージが必要です。

基本的に、各コード単位には独自の有効範囲があります。

# install.packages("modules") 
# Load library 
library("modules") 

# Create a basic module 
m <- module({ 
    .myList <- list() 
    myFunction <- function() { 
     .myList <<- c(.myList, 'test') 
    } 

    get <- function() .myList 
}) 
# Accessor 
m$get() 
# list() 

# Your function 
m$myFunction() 

# Modification 
m$get() 
# [[1]] 
# [1] "test" 

注意、我々はmyListから.myListに変数名を変更することで、少し例を微調整。だから、我々はこれを実行するuserfunction()

userFunction <- function() { 
    .myList <- c(.myList, 'test') 
} 

にそれを更新する必要があります、私たちは今、取得:

userFunction() 
# Error in userFunction() : object '.myList' not found 

希望通り。

さらに詳しい例については、modules vignetteを参照してください。

代わりに、環境(new.env())を定義し、myListをロードした後にロックすることができます。

1

これはすべて悪い考えです。地球環境への割り当てから(私はこれを行うパッケージを使用することはありません)、あなたのユーザーに驚くべきものを提供します。たぶん、S4クラスまたは参照クラスを使うべきです。

とにかく、バインディング(または、より良い実践に従えば環境)をロックすることができます。上級ユーザーはそれをやめることはありませんが、オブジェクトを変更したくないことは少なくとも知っています。

createLocked <- function(x, name, env) { 
    assign(name, x, envir = env) 
    lockBinding(name, env) 
    invisible(NULL) 
} 

createLocked(list(), "myList", globalenv()) 


myFunction <- function() { 
    unlockBinding("myList", globalenv()) 
    myList <- c(myList, 'test') 
    assign('myList', myList, envir = globalenv()) 
    lockBinding("myList", globalenv()) 
    invisible(NULL) 
} 

userFunction <- function() { 
    myList <- c(myList, 'test') 
    assign('myList', myList, envir = globalenv()) 
} 

myFunction() # runs successfully 
userFunction() 
#Error in assign("myList", myList, envir = globalenv()) : 
# cannot change value of locked binding for 'myList' 
関連する問題