R の変数スコート(レキシカルスコープとダイナミックスコープ)

変数スコープ

R の変数のスコープは基本的にレキシカルスコープである。しかしながら、evalsq 関数を利用してダイナミックスコープを実現することもできる。

レキシカルスコープ

あるスコープ内で変数が呼び出された時、自己のスコープ内でその変数が見つかからない場合は、その絶対的な親スコープから探そうとする。これがレキシカルスコープである。R は基本的にレキシカルスコープである。

x <- 10              # グローバルな変数

fA <- function() {
  print(x)           # fA の中に x が定義されていないため、その親スコープ内の x が利用される。(x = 10)
}

fB <- function() {
  x <- 20            
  print(x)           # fB の中に x が定義されているため、これを利用する。(x = 20)
}

fC <- function() {
  x <- 30
  fA()               # fA の絶対的な親は一番外側の x = 10 が利用される
  fB()               # fB の中に x が定義されているため x = 20 が利用される
  print(x)           # fC の中に x が定義されているため x = 30 が利用される
}

fC()
## [1] 10          # fA()の出力
## [1] 20          # fB()の出力
## [1] 30          # print(x)の出力

ダイナミックスコープ

R は基本的にレキシカルスコープであるが、evalsq 関数を利用することでダイナミックスコープを実現できる。ダイナミックスコープは、自己のスコープに変数が見つからない場合、相対的な親スコープから探そうとする特徴がある。

x <- 10

fA <- function() {
  print(evalq(x, parent.frame()))
}

fB <- function() {
  x <- 20            
  print(evalq(x, parent.frame()))
}

fC <- function() {
  x <- 30
  fA()                               # fA の相対的な親スコープは、fC なので、x = 30
  fB()                               # fB の相対的な親スコープは、fC なので、x = 30
  print(evalq(x, parent.frame()))     # fC の相対的な親スコープはグローバルなので、 x = 10
}

fC()
## [1] 30          # fA()の出力
## [1] 30          # fB()の出力
## [1] 10          # print(x)の出力

親環境

R で定義されている親環境は parent.envparent.frame とがある。

parent.env 絶対的な親環境を表す。
parent.frame 現在の位置から見た相対的な親環境を表す。