web-dev-qa-db-ja.com

::を介してパッケージ内の関数を呼び出すのは良い習慣ですか?

stringrbase64encなどの他のパッケージでいくつかの便利な関数を使用するR関数をいくつか書いています。最初にこれらのパッケージをロードするためにlibrary(...)またはrequire(...)を呼び出さずに、stringr::str_match(...)のように::を使用して必要な関数を直接参照するのは良いことですか?

それは一般的なケースで良い習慣ですか?それとも、どのような問題を引き起こす可能性がありますか?

41
Kun Ren

それはすべてコンテキストに依存します。

_::_は、同じ名前の異なるパッケージの関数namespace conflictsがある場合に主に必要です。 dplyrパッケージをロードすると、関数filterが提供されます。これは、デフォルトでfilterパッケージにロードされたstats関数と衝突(およびマスク)します。 。そのため、関数のstatsバージョンを使用する場合は、_stats::filter_で呼び出す必要があります。これは大量のパッケージをロードしないにも動機を与えます。パッケージから1つの関数だけが本当に必要な場合、特にパッケージが使用する他の関数をマスクすることがわかっている場合は、パッケージ全体をロードするよりも_::_を使用する方が良い場合があります。

コードではなくテキストで、_::_は非常に便利だと思います。 「filterパッケージのstats関数」よりも_stats::filter_を入力する方がはるかに簡潔です。

パフォーマンスの観点から見ると、_::_の使用には(非常に)小さな価格があります。長い間R-Core開発チームのメンバーであるMartin Maechlerが( r-develメーリングリスト(2017年9月) )に書いています

_::_のすべての使用はR関数呼び出しであることを多くの人は忘れているようであり、それを使用することは、すでにインポートされている名前を使用するだけに比べて非効率的です。

パフォーマンスペナルティは非常に小さく、数マイクロ秒程度であるため、高度に最適化されたコードが必要な場合にのみ問題になります。 _::_を使用するコード行を100万回実行すると、_::_を使用しないコードよりも1〜2秒長くかかります。

移植性に関して言えば、最初の数行を一目で確認して必要なパッケージを確認し、必要に応じてインストールしてから、他のことを深く理解するのを簡単にするため、スクリプトの先頭で明示的にパッケージをロードすると便利です。 、最初からやり直さないと完了できない長いプロセスの途中まで進んでいます。

余談library()よりもrequire()を優先するように同様の引数を作成できます。ライブラリはエラーを引き起こし、パッケージがそこになければ停止しますが、requireは警告しますが続行します。パッケージが存在しない場合のコードに緊急時対応計画がある場合は、必ずif (require(package)) ...を使用してください。ただし、パッケージなしでコードが失敗する場合は、library(package)を使用してください。 topなので、早く失敗します。

自分のパッケージ内

一般的な解決策は、DESCRIPTIONファイルで使用する必要がある他のパッケージをimportsにする独自のパッケージを作成することです。これらのパッケージは、パッケージのインストール時に自動的にインストールされるため、内部で_pkg::fun_を使用できます。または、それらをNAMESPACEファイルにインポートすることで、パッケージ全体をimportまたは選択的にimportFrom特定の関数を使用でき、_::_は不要です。これについては意見が異なります。 Martin Maechler(上記と同じr-develソース)は次のように述べています。

個人的には、::最近は特にNAMESPACEでimportFrom()を使用することを強く推奨するパッケージで、「過度に使用されている」という印象を持っているので、これはすべてパッケージのロード時に発生し、notパッケージのソース自体で_::_を使用します。

一方、tidyverse作成者のHadley Wickhamは、彼の R Packagesの本

パッケージがImportsではなくDESCRIPTIONにリストされますが、NAMESPACEにはリストされないのが一般的です。実際、これが私がお勧めすることです。パッケージをDESCRIPTIONにリストしてインストールされるようにしてから、常にpkg::fun()で明示的に参照してください。しない特別な理由がない限り、明示的にすることをお勧めします。

尊敬される2人のRエキスパートが反対の推奨事項を提示しているので、明快さ、効率性、保守性のニーズに最も合ったスタイルを選ぶべきだと言っても差し支えないと思います。


別のパッケージの1つの関数だけを頻繁に使用している場合は、コードをコピーして独自のパッケージに追加できます。たとえば、私はHmiscパッケージから_%nin%_を借用した個人用のパッケージを持っていますが、これは素晴らしい関数だと思いますが、Hmiscの他のものはほとんど使用しません。 。 _roxygen2_を使用すると、_@author_と_@references_を追加して、借用した関数のコードを適切に属性付けすることが簡単になります。これを行う場合は、パッケージライセンスに互換性があることも確認してください。

54
Gregor Thomas