まず、@ Spacedmanが言ったように、パッケージが最適ですが、他のオプションもあります。
S3メソッド
Rの元の「オブジェクト指向」はS3として知られています。Rのコードベースの大部分は、この特定のパラダイムを使用しています。それはplot()
あらゆる種類のオブジェクトのために働くものです。plot()
はジェネリック関数であり、Rコアチームとパッケージ開発者は、のために独自のメソッドを作成できますplot()
。厳密には、これらのメソッドには、関数がメソッドを定義するオブジェクトのクラスであるplot.foo()
whereのような名前が付いている場合があります。S3の利点は、使用することを(ほとんど)知る必要がなく、呼び出す必要がないことです。Rは、オブジェクトのクラスに基づいて、ディスパッチするメソッドを決定します。foo
plot()
plot.foo()
plot(bar)
plot()
bar
あなたの質問に対するあなたのコメントの中で、あなたはあなたがpopulate()
クラスのための(事実上)メソッドを持ち"crossvalidate"
そして"prod"
あなたが別々の.r
ファイルに保持する関数を持っていると述べています。これを設定するS3の方法は、次のことです。
populate <- function(x, ...) { ## add whatever args you want/need
UseMethod("populate")
}
populate.crossvalidate <-
function(x, y, z, ...) { ## add args but must those of generic
## function code here
}
populate.prod <-
function(x, y, z, ...) { ## add args but must have those of generic
## function code here
}
bar
与えられたクラスを持つオブジェクト"prod"
、呼び出し
populate(bar)
R呼び出しpopulate()
(ジェネリック)が発生し、名前の関数が検索されます。populate.prod
これは、のクラスであるためですbar
。それは私たちを見つけて、私たちがpopulate.prod()
最初に指定した引数をそれに渡す関数をディスパッチします。
したがって、完全な関数名ではなく、ジェネリックの名前を使用してメソッドを参照するだけであることがわかります。Rは、どのメソッドを呼び出す必要があるかを判断します。
2つのpopulate()
メソッドは、厳密にはジェネリック関数と同じ引数を持つ必要があることを除いて、非常に異なる引数を持つことができます。したがって、上記の例では、すべてのメソッドに引数x
とが必要...
です。(式オブジェクトを使用するメソッドには例外がありますが、ここではそれについて心配する必要はありません。)
パッケージの名前空間
R 2.14.0以降、Rには名前空間がずっと長く存在していましたが、パッケージの作成者から提供されていなくても、すべてのRパッケージに独自の名前空間がありました。
あなたの例では、populate()
ジェネリックを登録したいと思います。それはS3システムに2つのメソッドです。また、ジェネリック関数をエクスポートしたいと思います。通常、個々のメソッドをエクスポートする必要はありません。.R
したがって、パッケージソースのフォルダー内のファイルに関数をポップR
し、パッケージソースのトップレベルでという名前のファイルを作成しNAMESPACE
、次のステートメントを追加します。
export(populate) ## export generic
S3method(populate, crossvalidate) ## register methods
S3method(populate, prod)
次に、パッケージをインストールすると、呼び出すことができることに気付くでしょうが、プロンプトまたは別の関数から名前で直接etcpopulate()
を呼び出そうとすると、Rは文句を言います。populate.prod()
これは、個々のメソッドである関数が名前空間からエクスポートされていないため、名前空間の外部に表示されないためです。呼び出すパッケージ内の関数はすべてpopulate()
、定義したメソッドにアクセスできますが、パッケージ外の関数またはコードはメソッドをまったく認識できません。:::
必要に応じて、演算子を使用してエクスポートされていない関数を呼び出すことができます。
mypkg:::populate.crossvalidate(foo, bar)
mypkg
動作します。パッケージの名前はどこにありますか。
正直なところ、NAMESPACE
パッケージをインストールするとRがファイルを自動生成し、すべての関数を自動的にエクスポートするため、ファイルも必要ありません。そうすれば、2つのメソッドがpopulate.xxx()
(特定のメソッドはどこにあるかxxx
)として表示され、S3メソッドとして動作します。
関係する内容の詳細については、「R拡張機能の作成」マニュアルのセクション1「Rパッケージの作成」をお読みください。ただし、特にパッケージが自分で使用する場合は、yuoが必要ない場合はこの半分を実行する必要はありません。適切なパッケージフォルダ(つまりR
と)を作成し、ファイルをman
に貼り付けます。追加した場所に単一のファイルを書き込む.R
R
.Rd
man
\name{Misc Functions}
\alias{populate}
\alias{populate.crossvalidate}
\alias{populate.prod}
ファイルの先頭にあります。\alias{}
あなたが持っている他の機能のために追加してください。次に、パッケージをビルドしてインストールする必要があります。
代替使用sys.source()
ここで長期的に実行可能なオプションとして以下に言及することは本当にお勧めしませんが(できません!)、.r
最初に要求したように個々のファイルから機能を分離できる代替手段があります。これは、名前空間ではなく環境を使用することで実現され、パッケージの作成は含まれません。
このsys.source()
関数を使用して、.R
ファイルからRコード/関数を取得し、環境で評価することができます。.R
ファイルが関数を作成/定義しているときに、別の環境内でそれを調達すると、それらの関数はその環境でそこで定義されます。これらはデフォルトでは標準の検索パスに表示されないため、で定義されたpopulate()
関数はで定義された関数crossvalidate.R
と衝突しません。populate()
prod.R
2つの別々の環境を使用する限り。1セットの関数を使用する必要がある場合は、環境を検索パスに割り当てることができます。検索パス上で、環境はすべてに奇跡的に表示され、完了したら切り離すことができます。他の環境をアタッチ、使用、デタッチなど。または、などを使用して特定の環境でRコードが評価されるように調整できますeval()
。
私が言ったように、これは推奨される解決策ではありませんが、流行の後、あなたが説明する方法で機能します。例えば
## two source files that both define the same function
writeLines("populate <- function(x) 1:10", con = "crossvalidate.R")
writeLines("populate <- function(x) letters[1:10]", con = "prod.R")
## create two environments
crossvalidate <- new.env()
prod <- new.env()
## source the .R files into their respective environments
sys.source("crossvalidate.R", envir = crossvalidate)
sys.source("prod.R", envir = prod)
## show that there are no populates find-able on the search path
> ls()
[1] "crossvalidate" "prod"
> find("populate")
character(0)
次に、環境の1つを接続して、次のように呼び出しますpopulate()
。
> attach(crossvalidate)
> populate()
[1] 1 2 3 4 5 6 7 8 9 10
> detach(crossvalidate)
次に、他の環境で関数を呼び出します
> attach(prod)
> populate()
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
> detach(prod)
明らかに、特定の関数を使用するたびに、attach()
その環境を呼び出してから呼び出し、続いて呼び出しを行う必要がありdetach()
ます。これは苦痛です。
私はあなたがRコード(実際には式)が指定された環境で評価されるように手配できると言いました。たとえば、これにeval()
使用できます。with()
> with(crossvalidate, populate())
[1] 1 2 3 4 5 6 7 8 9 10
少なくとも今populate()
は、選択したバージョンを実行するために1回の呼び出しだけが必要です。ただし、関数をフルネームで呼び出す場合、たとえばpopulate.crossvalidate()
(コメントによると)with()
手間がかかりすぎる場合は、アイデアでさえ面倒になると思いますか?そしてとにかく、あなたがあなた自身のRパッケージを非常に簡単に持つことができるのに、なぜあなたはこれを使うのでしょうか。