1

動機

pkg関数呼び出しによって生成されたいくつかのオブジェクトを実行中のキャッシュに収集する R パッケージ (と呼びます) を開発しています。名前空間でキャッシュをオブジェクトとして実装するのは簡単ですlist(それを と呼びます.cache) 。pkgただし、ユーザーがキャッシュに直接干渉するのを防ぎたいと思います。これは、:::構文を介して常に公開できますpkg:::.cache

つまり.cache、オブジェクト指向プログラミングのプライベート フィールドと同様に保護したいと考えています。すべての操作は、「API フレーバー」を持つ ed 関数.cacheによって排他的に呼び出される内部ヘルパー関数によって実行する必要があります。@export

問題

そのため、名前空間でオブジェクトを定義するenvironment(それを と呼ぶ) という考えがあったので、... myを my に.vault入れることができます。.cache.vault

3

私の困惑は、次のような環境が R で参照によって.vault機能する数少ないものの 1 つであるということです。そのため、またはその内容を表示だけでなく変更にも公開することを恐れています。アクセサー関数を変更して、そのような露出を有効しないようにすることはできますが、その場で直接変更できる場合、そのような努力はすべて無駄です。pkg:::.vault.vaultpkg:::.get_cache().vault

走るな

例として、以下の危険な(?) コードについて考えてみましょう。最初に、「ターゲットを特定する」ために.S3MethodsClassesから内部環境を調べます。dplyr

dplyr:::.S3MethodsClasses
#> <environment: 0x7fab9c6c5310>

ls(dplyr:::.S3MethodsClasses)
#> [1] "grouped_df" "rowwise_df"

次に、オブジェクトを調べrowwise_dfて、価値のある「ターゲット」と見なします。

dplyr:::.S3MethodsClasses$rowwise_df
#> Virtual Class "rowwise_df" [package "dplyr"]
#> 
#> Slots:
#> 
#> Name:                .Data               names           row.names
#> Class:                list           character data.frameRowLabels
#> 
#> Name:             .S3Class
#> Class:           character
#> 
#> Extends:
#> Class "tbl_df", directly
#> Class "tbl", by class "tbl_df", distance 2
#  ...

dplyr最後に、名前空間のほとんどのオブジェクトとは異なり...

library(dplyr)

mutate <- NULL

dplyr::mutate
#> function (.data, ...) 
#> {
#>     UseMethod("mutate")
#> }
#> <bytecode: 0x7fab9c2f6120>
#> <environment: namespace:dplyr>

... .S3MethodsClasses points by referenceのような環境なので、その内容をその場で簡単に変更できます。

# "Copy" the pointer to allow `<-` assignment.
same_pointer <- dplyr:::.S3MethodsClasses

same_pointer
#> <environment: 0x7fab9c6c5310>



# Modify in place.
same_pointer$rowwise_df <- NULL

dplyr:::.S3MethodsClasses$rowwise_df
#> NULL

そのまま「金庫」が奪われる!

疑惑

答えはlockEnvironment()友人と一緒にここにあるのではないかと思いますが、アプリケーションは私を少し超えています. おそらく、環境.onLoadをセットアップするために何かを行うことができます。これは、それ自体とその中のバインディングの両方を edにしますが、名前空間内に入力される とアクセサー functionの間のアクティブなバインディングを作成する前ではありません。.vaultlock*().vault.cache.get_cache()pkg

ノート

名前空間.get_cache()から仲間の関数の外部で呼び出されたときのように、(ヘルパー) 関数を終了する機能を既に開発しています。pkgしたがって、 を公開するpkg:::.get_cache()と、ユーザーは.get_cache()手動で操作したり、独自のカスタム関数で操作したりできなくなります。

正規性

正規の回答を提供するのに十分な経験を積んだ R 開発者のアドバイス (もしあれば) に特に感謝します。

4

0 に答える 0