web-dev-qa-db-ja.com

割り当ての使用が悪いのはなぜですか?

この投稿( Rでの遅延評価–割り当ては影響を受けますか? )はいくつかの共通点をカバーしていますが、それが私の質問に答えるかどうかはわかりません。

assignファミリーをかなり前に発見したとき、私はapplyの使用をやめましたが、純粋に次のような状況での優雅さの理由でした。

names.foo <- letters
values.foo <- LETTERS
for (i in 1:length(names.foo))
  assign(names.foo[i], paste("This is: ", values.foo[i]))

これは次のように置き換えることができます。

foo <- lapply(X=values.foo, FUN=function (k) paste("This is :", k))
names(foo) <- names.foo

これが理由でもあります( http://cran.r-project.org/doc/FAQ/R-FAQ.html#How-can-I-turn-a-string-into-a-variable_003f )R-faqは、これは避けるべきだと言っています。

今、私はassignが一般的に嫌われていることを知っています。しかし、私が知らない他の理由はありますか?スコーピングや遅延評価が混乱する可能性があると思いますが、よくわかりません。そのような問題を示すサンプルコードは素晴らしいでしょう。

35
asb

実際、これら2つの操作はまったく異なります。 1つ目は26の異なるオブジェクトを提供し、2つ目は1つだけを提供します。 2番目のオブジェクトは、分析ではるかに使いやすくなります。したがって、assignの主な欠点、つまり、現在ある同様の名前の個々のオブジェクトをすべてまとめたり収集したりするために、常にgetを使用する必要があることをすでに示していると思います。地球環境の「ゆるい」。これらの26個の個別のオブジェクトを使用して連続して何かを行う方法を想像してみてください。 2番目の戦略には、単純なlapply(foo, func)で十分です。

そのFAQ引用は、実際には、割り当てを使用してから名前を割り当てる方が簡単だと言っているだけですが、それが「悪い」ことを意味するものではありませんでした。実際にはそうではないので、たまたま「機能が少ない」と読んでいます。割り当てられた値を返します。効果は副作用のようです(この場合、assign戦略は26の個別の副作用になります)。assignの使用は次のようになります。 「TrueRWay」、つまりデータオブジェクトを使用した関数型プログラミングを回避する方法として、グローバル変数を持つ言語から来ている人々に採用されています。ワークスペースを個別に散らかすのではなく、リストの使用法を学ぶ必要があります。名前付きアイテム。

使用できる別の割り当てパラダイムがあります。

 foo <- setNames(  paste0(letters,1:26),  LETTERS)

これにより、名前付きリストではなく名前付きアトミックベクトルが作成されますが、ベクトル内の値へのアクセスは、[に指定された名前で行われます。

33
42-

fortune(236)のソースとして、いくつかの例を追加すると思いました(fortune(174)も参照)。

まず、クイズ。次のコードについて考えてみます。

_x <- 1
y <- some.function.that.uses.assign(rnorm(100))
_

上記の2行のコードを実行した後、xの値は何ですか?

assign関数は、「遠隔作用」をコミットするために使用されます( http://en.wikipedia.org/wiki/Action_at_a_distance_(computer_programming) またはgoogleを参照)。これは多くの場合、見つけるのが難しいバグの原因です。

assignの最大の問題は、人々をより良い選択肢から遠ざける思考の道に導く傾向があることだと思います。簡単な例は、質問の2セットのコードです。 lapplyソリューションはよりエレガントであり、宣伝する必要がありますが、人々がassign関数について学ぶという単なる事実は、人々をループオプションに導きます。次に、ループで作成された各オブジェクトに対して同じ操作を実行する必要があると判断し(エレガントなソリューションが使用された場合は、別の単純なlapplyまたはsapplyになります)、偶数に頼りますgetapplyの両方とpasteへの醜い呼び出しを含むより複雑なループ。次に、assignに夢中になっている人は、次のようなことを試みます。

_curname <- paste('myvector[', i, ']')
assign(curname, i)
_

そして、それは彼らが期待したことを完全には行わず、Rについて不平を言う(私がブロックの周りを長い道のりを歩くことを選んだので隣の家が遠すぎると不平を言うのと同じくらい公正です)、またはさらに悪いことに、掘り下げますevalparseを使用して、構築された文字列を「機能」させます(これにより、fortune(106)fortune(181)になります)。

14
Greg Snow

assignenvironmentsとともに使用されることを意図していることを指摘したいと思います。

その観点から、上記の例の「悪い」ことは、適切ではないデータ構造(listまたはdata.framevectorの代わりに基本環境)を使用していることです。 ...)。

補足:environmentsの場合も、$および$<-演算子が機能するため、多くの場合、明示的なassignおよびgetは必要ありません。そこにも、どちらも。