次のスニペットでvairable'loco'の値を変更するにはどうすればよいですか。
poco <- function() {
func <- function(x) {
print(loco)
loco <- loco+x
}
loco <- 123
func(1)
func(2)
}
この関数は次の結果をもたらします。
> poco()
[1] 123
[1] 123
次のスニペットでvairable'loco'の値を変更するにはどうすればよいですか。
poco <- function() {
func <- function(x) {
print(loco)
loco <- loco+x
}
loco <- 123
func(1)
func(2)
}
この関数は次の結果をもたらします。
> poco()
[1] 123
[1] 123
poco <- function() {
func <- function(x) {
print(loco)
loco <<- loco+x
}
loco <- 123
func(1)
func(2)
}
この<<-
演算子は、外部スコープに割り当てます。(のようにassign(..., env=...)
)。ただし、コメントで述べたように、これは通常悪い考えです。問題全体の概要を説明する、これを拡張した2番目の質問をしたい場合は、他にももっと良い選択肢があると思います。
注意しないと、お<<-
尻に噛み付く可能性があります。このwiki記事を参照してください
最初の関数で何が起こっていたのかというと、関数は、スコープではなくローカルスコープに取り込まれ、ローカルスコープに割り当てられたときにloco <- loco + x
、スコープの外を探します。func
loco
func
loco
poco
お役に立てば幸いです。
Rには環境のスタックがあります。<-
したがって、単純なコマンドまたはコマンドを使用して関数内の変数を変更している間=
、その値は外部環境では変更されません。
そのためには、以下に示すように、いくつかのオプションがあります。
最初のオプション:
func <- function(x) {
print(loco)
# To modify value of "loco" just in the parent environment, but not globally
loco <<- loco+x
}
2番目の(より良い)オプション:
func <- function(x) {
print(loco)
# Again modifies the varaible just in the parent environment, not globally
assign("loco", loco + x, envir = sys.frame(-1))
}
そして3番目のオプション:
func <- function(x) {
print(loco)
# To modify the value of a global variable "loco"
assign("loco", loco + x, envir = .GlobalEnv)
}
次に、次のようになります。
loco <- 123
func(1) # 123
func(2) # 124
loco # 126
オプション1と2を使用すると、ネストされた関数定義が複数ある場合は、親関数だけで値を変更しますが、グローバルには変更しないことに注意してください。
poco <- function() {
func <- function(loco,x) {
print(loco)
loco <- loco+x
loco
}
loco <- 123
loco <- func(loco,1)
loco <- func(loco,2)
loco
}
loco_final <- poco()
#[1] 123
#[1] 124
loco_final
#[1] 126
loco
一般的に、関数で変更されないのは良いことです。これらの種類のグローバル変数を使用しないことで、変数がより大きなスクリプトのそれぞれに干渉しないことが保証されます。
とで変数を使用するとbla
しfunction_a
ますfunction_b
。の履歴に依存するため、関数呼び出しの結果を予測することは困難ですbla
。専門用語では、これは関数に副作用があると呼ばれます。これらを使用しないと、関数がより予測可能になり、デバッグが容易になります。さらに、スクリプトが大きくなると、新しい関数やコードスニペットbla
が変更され、関数で何が起こるかが変わるという問題を防ぐことができます。
一般に、関数に変数が必要な場合は、それを変数として渡します。ただし、Rは関数の内側から関数の外側へのスコーピングを許可しますが、その逆は許可しません。詳細については、この最近の質問も参照してください。