代入演算子=
と<-
R の違いは何ですか?
この例が示すように、演算子は少し異なります。
x <- y <- 5
x = y = 5
x = y <- 5
x <- y = 5
# Error in (x <- y) = 5 : could not find function "<-<-"
しかし、これが唯一の違いですか?
代入演算子=
と<-
R の違いは何ですか?
この例が示すように、演算子は少し異なります。
x <- y <- 5
x = y = 5
x = y <- 5
x <- y = 5
# Error in (x <- y) = 5 : could not find function "<-<-"
しかし、これが唯一の違いですか?
回答:
代入演算子
=
と<-
R の違いは何ですか?
あなたの例が示すように、=
及び<-
(それらが同じ式で混合した場合の評価の順序を決定する)わずかに異なる演算子の優先順位を有します。実際、?Syntax
R では、次の演算子優先順位テーブルが最高から最低まで提供されます。
… ‘-> ->>’ rightwards assignment ‘<- <<-’ assignment (right to left) ‘=’ assignment (right to left) …
しかし、これが唯一の違いですか?
あなたは代入演算子について尋ねていたので、はい、それが唯一の違いです。しかし、そうでなければ信じることは許されます。?assignOps
より多くの違いがあるという主張のRドキュメントですら:
演算子
<-
は任意の場所で使用できますが、演算子=
はトップレベル(たとえば、コマンドプロンプトで入力された完全な式)または式の括弧で囲まれたリスト内のサブ式の1つとしてのみ許可されます。
あまり細かくポイントを付けすぎないようにしましょう。Rのドキュメントは(微妙に)間違っています [ 1 ]。これは簡単に表示できます。必要なの=
は、(a)最上位のレベルでも、(b)式の括弧で囲まれたリストのサブ式(つまり{…; …}
)でもない演算子の反例を見つけることだけです。- 難しい話は抜きにして:
x
# Error: object 'x' not found
sum((x = 1), 2)
# [1] 3
x
# [1] 1
明らかに=
、コンテキスト(a)と(b)の外で、を使用して割り当てを実行しました。それで、コアR言語機能のドキュメントが何十年もの間間違っていたのはなぜですか?
これは、Rの構文では、記号=
が2つの異なる意味を持ち、日常的に混乱するためです。
=
どれどれ。
一般的な形式の任意のコードで…
‹function_name›(‹argname› = ‹value›, …)
‹function_name›(‹args›, ‹argname› = ‹value›, …)
… =
は、名前付き引数の受け渡しを定義するトークンです。これは代入演算子ではありません。さらに、一部の構文コンテキストで=
は完全に禁止されています。
if (‹var› = ‹value›) …
while (‹var› = ‹value›) …
for (‹var› = ‹value› in ‹value2›) …
for (‹var1› in ‹var2› = ‹value›) …
これらのいずれかを実行すると、「inbla›で予期しない '='」というエラーが発生します。
その他のコンテキストで=
は、代入演算子呼び出しを指します。特に、部分式を括弧で囲むだけで、上記の(a)が有効になり、(b)割り当てが有効になります。たとえば、次は割り当てを実行します。
median((x = 1 : 10))
だけでなく:
if (! (nf = length(from))) return()
さて、あなたはそのようなコードがひどいことに反対するかもしれません(そしてあなたは正しいかもしれません)しかし、私がこのコードを取ったbase::file.copy
(置き換え機能<-
で=
) -それはコアRのコードベースの多くに浸透パターンです。
ジョン・チェンバーズによるオリジナル解説 Rのドキュメントは、おそらくに基づいており、実際にこれを正しく説明します。
[
=
割り当ては]文法の2つの場所でのみ許可されています。中括弧または追加の括弧のペアによって、周囲の論理構造から分離されている場合。
告白:私は以前に嘘をついた。演算子と演算子の間には、もう1つの違いがあります。それらは、別個の関数を呼び出します。デフォルトでは、これらの関数は同じことを行いますが、どちらかを個別にオーバーライドして動作を変更できます。対照的に、そして(左から右への代入)は構文的には異なりますが、常に同じ関数を呼び出します。一方をオーバーライドすると、もう一方もオーバーライドされます。これを知ることはめったに実用的ではありませんが、いくつかの楽しいシェニガンに使用できます。=
<-
<-
->
?
は実際にはとの中間に=
あり<-
、をオーバーライドするときに重要な結果をもたらし、?
それ以外の場合は事実上ありません。
main/gram.y
)によると、の優先順位?
は正しく文書化されており、およびのどちらよりも低くなっ=
てい<-
ます。
=
、解析ツリーが作成される前に特別な扱いを受けると思います。関数の引数に関連しているかもしれませfoo(x = a ? b)
ん=
が、式の残りの部分を解析する前に検索することは理にかなっています。
関数呼び出しで引数の値を設定するために使用すると、代入演算子の違いがより明確になります。例えば:
median(x = 1:10)
x
## Error: object 'x' not found
この場合、x
は関数のスコープ内で宣言されているため、ユーザーワークスペースには存在しません。
median(x <- 1:10)
x
## [1] 1 2 3 4 5 6 7 8 9 10
この場合、x
はユーザーワークスペースで宣言されているため、関数呼び出しが完了した後で使用できます。
<-
Sプラスの(非常に)古いバージョンとの互換性のために、(関数シグネチャ以外で)割り当てに使用するためのRコミュニティの一般的な好みがあります。スペースは、次のような状況を明確にするのに役立ちます。
x<-3
# Does this mean assignment?
x <- 3
# Or less than?
x < -3
ほとんどのR IDEには、入力を<-
簡単にするためのキーボードショートカットがあります。 Ctrl+ =アーキテクト、Alt+ -RStudio(Option+- MacOSの下)、Shift+ -のEmacs + ESS内(下線)。
あなたが書い希望する場合=
に<-
はなく(例えば、CRAN上)公にリリースされたコードのためのより一般的な代入記号を使用したい場合、あなたはのいずれかを使用することができますtidy_*
の機能をformatR
自動的に交換するパッケージ=
で<-
。
library(formatR)
tidy_source(text = "x=1:5", arrow = TRUE)
## x <- 1:5
「なぜx <- y = 5
エラーをスローするが、スローしないのx <- y <- 5
か」という質問への回答 「パーサーに含まれる魔法にかかっています」です。Rの構文には、何らかの方法で解決する必要があるあいまいなケースが多数含まれています。パーサーは、=
または<-
が使用されたかどうかに応じて、式のビットを異なる順序で解決することを選択します。
何が起こっているのかを理解するには、割り当てが割り当てられた値を暗黙的に返すことを知っておく必要があります。たとえば、を明示的に印刷することで、より明確に確認できますprint(x <- 2 + 3)
。
第2に、割り当てに接頭表記を使用する方が明確です。そう
x <- 5
`<-`(x, 5) #same thing
y = 5
`=`(y, 5) #also the same thing
パーサーは次のx <- y <- 5
ように解釈します
`<-`(x, `<-`(y, 5))
私たちは、それが期待するかもしれないx <- y = 5
次のようになり
`<-`(x, `=`(y, 5))
しかし実際には次のように解釈されます
`=`(`<-`(x, y), 5)
これは、ヘルプページに示されているように、=
がよりも優先順位が低いためです。<-
?Syntax
median((x = 1:10))
と同じ効果がありmedian(x <- 1:10)
ます。
x <- x = 5
解釈の仕方の説明が少し間違っていることに気づきました。実際には、Rはそれを解釈します`<-<-`(x, y = 5, value = 5)
(それ自体がとほぼ同じですtmp <- x; x <- `<-<-`(tmp, y = 5, value = 5)
)。うわぁ!
=
関数呼び出しで使用する方法は代入を実行せず、代入演算子ではありません。これは完全に異なる解析済みR式であり、たまたま同じ文字を使用しているだけです。さらに、表示するコードx
は関数のスコープ内で「宣言」されていません。関数宣言は、その宣言を実行します。関数呼び出しはそうではありません(名前付き...
引数では少し複雑になります)。
GoogleのRスタイルガイドでは、「=」の割り当てを禁止することで問題を簡素化しています。悪い選択ではありません。
https://google.github.io/styleguide/Rguide.xml
Rマニュアルでは、5つの代入演算子すべてについて詳しく説明しています。
http://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html
x<-y
ときの欠点はx < -y
、私が個人的に好むほど私を悩ませること=
です。あなたのコードが空白の存在に依存しているのは私には良くないようです。スタイルのアドバイスとしてスペーシングを提案することは問題ありませんが、スペースがあるかどうかにかかわらず、コードの実行方法は異なりますか?コードを再フォーマットしたり、検索と置換を使用したりすると、空白が消えてコードがおかしくなることがあります。これはの問題ではありません=
。IIUC、禁止=
することは " <-
" を要求することと同じです。つまり、「<-
」だけでなく、スペースを含む3文字。
TRUE
R は0以外を考慮していることに注意してください。したがって、x
がより小さいかどうかをテストする場合は-y
、if (x<-y)
警告やエラーが発生せず、正常に動作しているように見える可能性があります。それだけだろうFALSE
ときy=0
に、しかし。
=
して使用する場合<-
、の追加の手順がgrep "[^<]<-[^ ]" *.R
不要であると主張するのは困難です。=
そのような必要はありませんgrep
。
<-
使用できるのになぜ目と指を傷つけるの=
ですか?99.99%の時間=
で結構です。時々あなた<<-
はそれを必要とします、それは異なる歴史です。
x = y = 5
x = (y = 5)
代入演算子は右から左に「グループ化」され、機能するため、と同等です。意味:5をy
に割り当て、数値5を残します。そして、その5をに割り当てx
ます。
これはと同じではなく、(x = y) = 5
機能しません!意味:の値に割り当てるy
にはx
値を残し、y
。そして、5に割り当てます、うーん...、正確には何ですか?
さまざまな種類の代入演算子を混在させると、<-
はよりも強くバインドされ=
ます。したがってx = y <- 5
、はと解釈されますx = (y <- 5)
。これは、意味のあるケースです。
残念ながら、はとx <- y = 5
解釈されますが(x <- y) = 5
、これは機能しません。
優先順位(バインディング)とグループ化の規則については?Syntax
、と?assignOps
を参照してください。
<- <<-
上にあるように言ったように=
、これは<-
最初に実行されることを意味します。したがって、x <- y = 5
として実行する必要があります(x <- y) = 5
。
John Chambers氏によれば、この演算子=
は「最上位」でのみ許可されif
ています。つまり、のような制御構造では許可されておらず、次のプログラミングエラーが違法になります。
> if(x = 0) 1 else x
Error: syntax error
彼が書いているように、「制御式で新しい割り当て形式[=]を許可しないことにより、他のS割り当てよりも等号演算子の可能性が高いプログラミングエラー(上記の例など)を回避できます。」
「中かっこまたは追加の括弧のペアによって周囲の論理構造から分離されている」場合、これif ((x = 0)) 1 else x
をうまく処理できます。
x==0
あり、ほとんどの場合、代わりに意味されます。
x=0
割り当てよりも優先するのに十分な理由がありx<-0
ます!
=
ので=
、できるだけ使用しないことを選択します==
。
if(x = 0) 1 else x
エラーをスローし、バグを見つけて修正するのに役立ちます。if(x <- 1) 1 else x
エラーをスローせず、非常に混乱しています。
else
値を常に返す無用のコードがあります。そのように記述するつもりでしたか?」と言いますが、それは夢のようなものかもしれません...
演算子<-
と=
、それらが評価される環境に割り当てます。演算子<-
は任意の場所で使用できますが、演算子=
はトップレベル(たとえば、コマンドプロンプトで入力された完全な式)または式の括弧で囲まれたリスト内のサブ式の1つとしてのみ許可されます。
x <- 42
、それ自体がステートメントです。でif (x <- 42) {}
、それは表現であり、有効ではありませんでしょう。明確に言うと、これはあなたが地球環境にいるかどうかとは関係ありません。
1 + (x = 2)
function() x = 1
、repeat x = 1
、if (TRUE) x = 1
....
これは、これら2つの演算子の違いを理解する上でも役立ちます。
df <- data.frame(
a = rnorm(10),
b <- rnorm(10)
)
最初の要素の場合、Rには値と固有名が割り当てられていますが、2番目の要素の名前は少し奇妙に見えます。
str(df)
# 'data.frame': 10 obs. of 2 variables:
# $ a : num 0.6393 1.125 -1.2514 0.0729 -1.3292 ...
# $ b....rnorm.10.: num 0.2485 0.0391 -1.6532 -0.3366 1.1951 ...
Rバージョン3.3.2(2016-10-31); macOSシエラ10.12.1
data.frame
提供された変数の名前をデータフレームの要素の名前として使用しようとします)
make.names("b <- rnorm(10)")
ます。
<-
ように、シンボルの起源は、実際には単一の<-
キーが付いていた古いAPLキーボードに由来しています。