2012-09-26 9 views
36

私はRでパッケージを開発しています。私はたくさんの関数を持っていますが、その中にはいくつかのグローバル変数が必要です。パッケージ内のグローバル変数はどのように管理するのですか?Rのパッケージ内のグローバル変数

私は環境について何かを読んだことがありますが、それがどのように機能するのか分かりません。

+0

具体的な状況を詳しく説明してください。それから、あなたは、代替案を見つけるのを助けることができます。 –

+0

http://stackoverflow.com/questions/5526322/examples-of-the-perils-of-globals-in-r-and-stata –

答えて

9

一般に、グローバル変数は、悪いです。なぜ彼らが悪いのかという原則は、パッケージ内の相互接続を最小限に抑えたいということです。これらの相互接続は、多くの場合、関数が副作用を引き起こす。すなわち、入力引数に結果だけでなく、一部のグローバル変数の値にも依存する。特に機能の数が増えると、デバッグするのが難しくなります。

Rのグローバル変数については、SO postを参照してください。

あなたのコメントに応じて編集: 代わりに、必要な情報を必要な機能に渡すことができます。

token_information = list(token1 = "087091287129387", 
         token2 = "UA2329723") 

、引数としてそれを持っているために、この情報を必要とするすべての機能を必要とする:あなたは、この情報が含まれている新しいオブジェクトを作成することができ

do_stuff = function(arg1, arg2, token) 
do_stuff(arg1, arg2, token = token_information) 

それは明らかである。このようにして、コードからということトークン情報が関数内に必要であり、独自の関数をデバッグすることができます。さらに、関数はその入力引数によって完全に決定されるため、この関数には副作用はありません。典型的なユーザースクリプトは、次のようになります。

token_info = create_token(token1, token2) 
do_stuff(arg1, arg2, token_info) 

これはもっとわかりやすいものです。

+2

答えをありがとう。私はプログラミングの経験があり、グローバル変数は一般的にnogoであることを知っています。しかし、私はサービスへのAPIアクセスを確立しています。このサービスに接続するためには、関数に2つのトークンが必要です。これらのトークンは、すべての関数によってアクセス可能でなければなりません。私が思いついたのは、このデータを格納する.RDataファイルを作成することですが、それは悪い理想のようです。 – Rimbaud

+3

通常のRパターンはトークンを保持する何らかの「ハンドル」オブジェクトを持ち、そのハンドルを関数に渡します。これにより、異なるトークンを持つ複数の同時セッションを持つこともできます。これがデータベースアクセスのパターンです。 – Spacedman

+0

@Spacedman +1まさに私が思ったものです –

13

あなたは設定することができoption、例えば

options("mypkg-myval"=3) 
1+getOption("mypkg-myval") 
[1] 4 
+1

これは正確にどこに保存されますか? – Rimbaud

+0

@Rimbaud 'base'パッケージにある' .Options'というペアリストです。 – James

+0

これは、パッケージがロードされているRセッションのグローバルオプションリストに格納されます。 '?options'を参照してください。 –

2

質問は不明である:

  • ちょうど1 Rプロセスまたはいくつ?

  • ただ1つのホスト上で、または複数のマシンにまたがっていますか?

  • 一般的なファイルアクセスはありますか?複雑さの増すために

、私は、ファイル、RSQliteパッケージまたはRedisのインスタンスからの読み取り/設定するには、(私のお気に入り:) rredisパッケージを経由してSQLiteのバックエンドを使用すると思います。

37

環境を通じてパッケージローカル変数を使用できます。これらの変数は、パッケージ内の複数の関数で使用できますが、ユーザーには(簡単に)アクセスできず、ユーザーの作業領域を妨げません。すばやく簡単な例は次のとおりです。

pkg.env <- new.env() 

pkg.env$cur.val <- 0 
pkg.env$times.changed <- 0 

inc <- function(by=1) { 
    pkg.env$times.changed <- pkg.env$times.changed + 1 
    pkg.env$cur.val <- pkg.env$cur.val + by 
    pkg.env$cur.val 
} 

dec <- function(by=1) { 
    pkg.env$times.changed <- pkg.env$times.changed + 1 
    pkg.env$cur.val <- pkg.env$cur.val - by 
    pkg.env$cur.val 
} 

cur <- function(){ 
    cat('the current value is', pkg.env$cur.val, 'and it has been changed', 
     pkg.env$times.changed, 'times\n') 
} 

inc() 
inc() 
inc(5) 
dec() 
dec(2) 
inc() 
cur() 
+7

これは便利なことですが、変数コンテナとして環境を作成する際の安全対策として、親環境を 'emptyenv()'に設定するのが一般的です。検索パス: 'new.env(parent)= newenv()'の代わりに 'new.env(parent = emptyenv())'です。 – egnha

関連する問題