0Pricing
R Academy · レッスン

グローバルスコープとローカルスコープ

.GlobalEnv、関数Environment、クロージャの違いを理解します。

「グローバルスコープとローカルスコープ」はCoddyKit上の無料R Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはR Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 R Academyコースには全4レッスンが含まれています。

関数内のローカル変数

関数本体内で<-または=を使って代入した変数は、その関数に対してローカルです。これらは関数自身の環境に作成され、関数が戻ると消滅します。呼び出し元のスコープに影響を与えることはありません。

x <- 'global'
f <- function() {
  x <- 'local'   # creates a new local binding, does not modify global x
  cat('Inside f: x =', x, '\n')
}
f()
cat('Outside f: x =', x, '\n')  # still 'global'

関数の引数はローカル変数

関数の引数もローカル変数です。関数内で引数を変更しても、呼び出し元の環境にある引数には影響しません。Rは引数を値渡しします(変更時にコピーされる仕組みです)。

double_it <- function(n) {
  n <- n * 2      # modifies local copy only
  cat('Inside:', n, '\n')
}
my_n <- 5
double_it(my_n)
cat('Outside:', my_n, '\n')  # still 5

グローバル代入のための <<-

<<-(スーパー代入)は、親チェーンを上にたどり、最初に見つかった一致するバインディングに代入します。どこにも一致するものがない場合は、グローバル環境にバインディングを作成します。<<-を使いすぎると関数の動作を把握しにくくなるため、慎重に使ってください。

total <- 0
add_to_total <- function(x) {
  total <<- total + x
}
add_to_total(10)
add_to_total(25)
add_to_total(5)
cat('Total:', total, '\n')

<<- はチェーンを上に検索する

<<-は無条件にグローバル環境へ代入するわけではありません。親チェーンを上にたどり、名前がすでに存在する最初の環境に代入します。変数が包含する関数に存在する場合は、その環境の変数が更新されます。

outer <- function() {
  n <- 0
  increment <- function() n <<- n + 1
  increment()
  increment()
  cat('n in outer:', n, '\n')  # n was in outer's env, updated there
}
outer()
# n does NOT appear in global env
cat('n in global:', exists('n', envir = globalenv()), '\n')

明示的な環境指定のための assign()

assign('name', value, envir = e)は、指定した環境に直接代入します。<<-よりも明示的で、環境オブジェクトを持っていて、そこに正確に値を設定したい場合に便利です。

my_env <- new.env(parent = emptyenv())
assign('score', 95, envir = my_env)
assign('name', 'Alice', envir = my_env)
cat('score:', get('score', envir = my_env), '\n')
cat('name :', get('name',  envir = my_env), '\n')

local() — 独立したコードブロック

local({...})は、式を新しいローカル環境で評価します。ブロック内で作成した変数がグローバル環境に漏れ出すことはありません。ワークスペースを汚さずに一時的な計算を行いたい場合に便利です。

result <- local({
  temp1 <- 100
  temp2 <- 200
  temp1 + temp2   # the last expression is returned
})
cat('result:', result, '\n')
cat('temp1 in global:', exists('temp1'), '\n')  # FALSE

分離における local() と関数の違い

local()と即時実行関数は、どちらもスコープを分離できます。1回限りの分離にはlocal()のほうが簡潔で、ロジックを再利用またはテストしたい場合は名前付き関数のほうが適しています。

# Option A: local()
result_a <- local({
  x <- 7
  y <- 3
  x * y
})
# Option B: immediately invoked function
result_b <- (function() {
  x <- 7
  y <- 3
  x * y
})()
cat(result_a, result_b, '\n')
cat('x in global:', exists('x'), '\n')

関数からグローバル変数を読み取る

関数は特別な構文を使わずに、包含スコープ(グローバルスコープなど)の変数を読み取れます。これは標準的なレキシカルスコープの動作です。ただし、グローバル状態に大きく依存すると関数のテストが難しくなるため、可能な場合は明示的な引数を使ってください。

tax_rate <- 0.20   # global configuration
apply_tax <- function(price) {
  price * (1 + tax_rate)  # reads tax_rate from global
}
cat(apply_tax(100), '\n')
cat(apply_tax(250), '\n')

変数のシャドーイング

ローカル変数がグローバル変数と同じ名前を持つ場合、ローカルのバインディングがグローバルのバインディングをシャドーイングします。関数内ではローカル側が使われ、グローバル側は変更されません。意図せず行うと、見つけにくいバグの原因になります。

mean <- 99   # shadows base R's mean() function
cat(mean, '\n')   # prints 99, not the function
# To call the real mean, use base:: prefix
cat(base::mean(c(1, 2, 3, 4, 5)), '\n')
rm(mean)   # remove the shadow

function() の環境

関数が呼び出されるたびに、Rはその呼び出し専用の新しい環境を作成し、関数の包含環境を親に設定します。再帰呼び出しの場合も含め、異なる呼び出しのローカル変数が互いに干渉することはありません。

factorial_r <- function(n) {
  # Each recursive call has its own local n
  if (n <= 1) return(1)
  n * factorial_r(n - 1)
}
cat('5! =', factorial_r(5), '\n')
cat('7! =', factorial_r(7), '\n')

変数を削除する rm()

rm('name')またはrm(name)は、現在の環境(または指定した環境)からバインディングを削除します。一時変数の後片付けに使えます。特定の環境から削除するには、envir = eを指定します。

x <- 42
y <- 'hello'
cat('Before rm:', ls(), '\n')
rm(x)
cat('After rm(x):', exists('x'), '\n')
rm('y')
cat('After rm(y):', exists('y'), '\n')

確認問題

<<-は通常の<-にはない、どのような動作をしますか。

スコープ:重要なポイント

グローバルスコープとローカルスコープに関する重要なポイント:

  • 関数内の<-はローカル変数を作成します。グローバル変数は変更されません
  • 関数の引数はローカルです。Rは値渡しします(変更時にコピーされます)
  • <<-は親チェーンを上にたどり、最初に一致したバインディングを変更します
  • assign('x', val, envir=e)は環境を明示して代入するために使います
  • local({...})は名前付き関数を作成せずに、一時的なスコープを提供します
  • mean、c、Tなどの重要な名前をシャドーイングしないでください
# Demonstrate local + <<- cleanly
running_sum <- 0
local({
  values <- c(10, 20, 30, 40)
  for (v in values) running_sum <<- running_sum + v
})
cat('Running sum:', running_sum, '\n')
cat('values in global:', exists('values'), '\n')

よくある質問

「グローバルスコープとローカルスコープ」レッスンは無料ですか?

はい。「グローバルスコープとローカルスコープ」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、R Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 R Academyコースには全4レッスンが含まれています。

「グローバルスコープとローカルスコープ」で何を学びますか?

.GlobalEnv、関数Environment、クロージャの違いを理解します。 ブラウザで直接実行するハンズオンコードでR Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

R Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのR Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「グローバルスコープとローカルスコープ」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このR Academyレッスンでコードを書いて実行できますか?

はい。すべてのR Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. RのEnvironmentとは
  2. レキシカルスコープの規則
  3. グローバルスコープとローカルスコープ
  4. Environmentの作成と確認
← R Academyに戻る