[R] Variable 性質

程式語言:R
官網

簡介:variable scope 與 傳遞

Global vs. Local

function 內自成一區,為 Lexical scope
如下範例,進入 function 時,並看不到外部的 x,所以皆為 character(0)
所以更改的值,自然也無法反應到外部
但此時若想印出 x ,會發現仍有值,這是因為當發現無 x 時,會再往外找,直到 .GlobalEnv
f <- function()
{
    print("In f")
    # 目前有的物件
    print(ls())
    # character(0)
    print(x)
    # [1] 10
    
    x <- 100
    g <- function()
    {
        print("In g")
        # 目前有的物件
        print(ls())
        # character(0)
        print(x)
        # [1] 100
        
        x <- 1000
        # 目前的環境
        print(environment())
        # <environment: 0x0000000017f504a0>
        
        #目前有的物件
        print(ls())
        # [1] "x"
        
        print(x)
        # [1] 1000
        
        print("Out g")
    }
    g()
    
    # 目前的環境
    print(environment())
    # <environment: 0x0000000017f505b8>
    
    # 目前有的物件
    print(ls())
    # [1] "g" "x"
    
    print(x)
    # [1] 100
    
    print("out f")
}

x <- 10
f()
# 目前的環境
# 也就是 .GlobalEnv
print(environment())
# 目前有的物件
print(ls())
# [1] "f" "x"

print(x)
# [1] 10
print(.GlobalEnv$x)
# [1] 10

# result
# [1] "In f"
# character(0)
# [1] 10
# [1] "In g"
# character(0)
# [1] 100
# <environment: 0x000000001218f368>
# [1] "x"
# [1] 1000
# [1] "Out g"
# <environment: 0x0000000012190e90>
# [1] "g" "x"
# [1] 100
# [1] "out f"
# <environment: R_GlobalEnv>
# [1] "f" "x"
# [1] 10
# [1] 10

強制指定
利用 <<- 將會直接往上層找符合的變數改變值,故原層的不變
若到 .GlobalEnv 都沒找到,則在 .GlobalEnv 建立新變數
f <- function()
{
    print("In f")
    x <- list(a=10)
    
    g <- function()
    {
        print("In g")
        x <- list(a=1)
        # 直接往上層找 x,直到 .GlobalEnv
        x$a <<- 100
        
        print(x$a)
        # [1] 1
        
        print("Out g")
    }
    g()
    print(x$a)
    # [1] 100
    
    print("out f")
}

x <- list(a=10)
print(x$a)
# [1] 10

f()

print(x$a)
# [1] 100

# result
# [1] 10
# [1] "In f"
# [1] "In g"
# [1] 1
# [1] "Out g"
# [1] 100
# [1] "out f"
# [1] 10

package variable
如何指定 package 的變數
<package name>::<variable name>
ggplot2::diamonds
# A tibble: 53,940 × 10
#   carat       cut color clarity depth table price     x     y     z
#   <dbl>     <ord> <ord>   <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
#1   0.23     Ideal     E     SI2  61.5    55   326  3.95  3.98  2.43
#2   0.21   Premium     E     SI1  59.8    61   326  3.89  3.84  2.31
#3   0.23      Good     E     VS1  56.9    65   327  4.05  4.07  2.31
#4   0.29   Premium     I     VS2  62.4    58   334  4.20  4.23  2.63
#5   0.31      Good     J     SI2  63.3    58   335  4.34  4.35  2.75
#6   0.24 Very Good     J    VVS2  62.8    57   336  3.94  3.96  2.48
#7   0.24 Very Good     I    VVS1  62.3    57   336  3.95  3.98  2.47
#8   0.26 Very Good     H     SI1  61.9    55   337  4.07  4.11  2.53
#9   0.22      Fair     E     VS2  65.1    61   337  3.87  3.78  2.49
#10  0.23 Very Good     H     VS1  59.4    61   338  4.00  4.05  2.39
# ... with 53,930 more rows

Mutable vs. Immutable

事實上幾乎所有 R objects 都是 immutable,除了 Reference class 等
如下範例,可以看到 R 的 list 傳遞為 call by value
f <- function(x)
{
    print("In f")
    
    x$a <- 100
    g <- function(x)
    {
        print("In g")
        
        x$a <- 1000
        
        print(x$a)
        # [1] 1000
        
        print("Out g")
    }
    g(x)
    
    print(x$a)
    # [1] 100
    
    print("out f")
}

x <- list(a=10)
f(x)

print(x$a)
# [1] 10

# result
# [1] "In f"
# [1] "In g"
# [1] 1000
# [1] "Out g"
# [1] 100
# [1] "out f"
# [1] 10

替代方案
environments
每次呼叫都從設定的 env 讀值
my.new.env <- new.env()

f <- function()
{
    print("In f")
    
    my.new.env$x$a <- 100
    
    print(my.new.env$x$a)
    # [1] 100
    
    print("out f")
}

my.new.env$x <- list(a=10)
f()

print(my.new.env$x$a)
# [1] 100

# result
# [1] "In f"
# [1] 100
# [1] "out f"
# [1] 100

RC(Reference class)
f <- function(x)
{
    print("In f")
    
    x$a <- 100
    
    print(x$a)
    # [1] 100
    
    print("out f")
}

X <- setRefClass("X", fields=list(a='numeric'))
x <- X(a=10)
print(x$a)
# [1] 10

f(x)

print(x$a)
# [1] 100

# result
# [1] 10
# [1] "In f"
# [1] 100
# [1] "out f"
# [1] 100

參考

R Environment and Scope
R 環境空間與函數

留言