21

オブジェクトの名前変更に関するこの基本的な質問とそれに対する @Shane の回答を読み、遅延評価を指摘しました。assignこれも怠惰に評価されているのだろうか。ここのように:

assign("someNewName",someOldObject)
rm(someOldObject)

私がこれについて疑問に思う理由は、次の使用例です: それぞれが と という 2 つの属性を持つ 10,000 以上の R オブジェクトを取得したとoriginalNameadditionalNameます。ここで、これら 2 つの属性を失わずに、ユーザーがある名前から別の名前に効率的に切り替えることができる関数を作成したいと考えています。ざっくりこんな感じ…

編集: @Hadley の入力に基づいて、コードを変更しました。

switchObjectName <- function(x) {
  n1 <- attributes(x)$originalName
  n2 <- attributes(x)$additionalName
  objName <- deparse(substitute(x))
  if(objName == n1) {
    delayedAssign(n2,x,assign.env=.GlobalEnv)
  } else {
    delayedAssign(n1,x,assign.env=.GlobalEnv)
  }
  rm(list=c(objName),envir=.GlobalEnv)    
}

rmこれはうまくいきますが、ステートメントを正しくするのにかなり苦労しました。私は試みrm(objName,envir=.GlobalEnv)ましたが、それを動作させることができませんでしたが、objName は間違いなく文字であり、deparse(substitute(x).

4

1 に答える 1

6

一般に、R 言語には値のセマンティクスがあります。割り当ては、とが同じオブジェクトの独立したコピーになることx <- yを意味します (とが独立して更新されます)。の単純な実装では、常にメモリが割り当てられ、完全にコピーされます。GNU-R は代わりにコピー オン ライト メカニズムを使用し、更新が実際に発生するまでコピーを延期します。これにより、更新が発生しない場合にメモリ/実行時間を節約できます。R ユーザーはこの最適化について知る必要はなく、完全に透過的です (メモリ不足エラーなどのまれなケースを除く)。このメカニズムは、asおよびequalとして記述された代入に適用されます。xyyxx <- yxyx <- yassign("x", y)

遅延評価は言語の設計の一部であり、R ユーザー/プログラマーに表示されます。関数に引数として渡されfoo(ls())た式 (渡された式 isls()など) は、呼び出された関数の実装で必要な場合にのみ、遅延評価されます。

delayedAssignR ユーザー/プログラマーに見える低レベル関数ですが、実際にはパッケージの遅延読み込みにのみ使用され、ユーザー プログラムでは必要ありません。delayedAssign変数の値を計算する式を指定できます。計算は、変数が初めて読み込まれた場合にのみ遅延して行われます。

したがって、質問に答えるために、R での代入は、コピー オン ライト メカニズムが使用されるという点で常に「遅延」です。代入の右辺の計算も ( を使用してdelayedAssign) 遅延する可能性がありますが、これはユーザー プログラムで必要/使用されるべきではありません。

変数の「名前変更」については、使用する必要はないと思いますdelayedAssign(右側が計算されないため)。これは状況をより複雑にするだけであり、簿記delayedAssignが行わなければならないため、パフォーマンスのオーバーヘッドが発生する可能性があります。変数の名前を変更する必要がある場合は、通常の割り当てを使用します。

コードを明確にするために、環境から変数を削除したり、関数からグローバル環境に代入したりすることを可能な限り避けようとします。たとえば、新しいリストを作成して、新しいバインディング (変数) をそれに挿入します。

コピー オン ライト メカニズムについて言及しましたが、GNU-R の現在の実装では、説明されている解決策のいずれかによって、変数の名前が変更されていなければ不要なメモリ コピーが発生する可能性があります。これを R レベルで回避する方法はありません。

于 2016-10-17T10:32:06.653 に答える