[R] Variable 性質

程式語言:R
官網

簡介:variable scope 與 傳遞

Global vs. Local

function 內自成一區,為 Lexical scope
如下範例,進入 function 時,並看不到外部的 x,所以皆為 character(0)
所以更改的值,自然也無法反應到外部
但此時若想印出 x ,會發現仍有值,這是因為當發現無 x 時,會再往外找,直到 .GlobalEnv
  1. f <- function()
  2. {
  3. print("In f")
  4. # 目前有的物件
  5. print(ls())
  6. # character(0)
  7. print(x)
  8. # [1] 10
  9. x <- 100
  10. g <- function()
  11. {
  12. print("In g")
  13. # 目前有的物件
  14. print(ls())
  15. # character(0)
  16. print(x)
  17. # [1] 100
  18. x <- 1000
  19. # 目前的環境
  20. print(environment())
  21. # <environment: 0x0000000017f504a0>
  22. #目前有的物件
  23. print(ls())
  24. # [1] "x"
  25. print(x)
  26. # [1] 1000
  27. print("Out g")
  28. }
  29. g()
  30. # 目前的環境
  31. print(environment())
  32. # <environment: 0x0000000017f505b8>
  33. # 目前有的物件
  34. print(ls())
  35. # [1] "g" "x"
  36. print(x)
  37. # [1] 100
  38. print("out f")
  39. }
  40.  
  41. x <- 10
  42. f()
  43. # 目前的環境
  44. # 也就是 .GlobalEnv
  45. print(environment())
  46. # 目前有的物件
  47. print(ls())
  48. # [1] "f" "x"
  49.  
  50. print(x)
  51. # [1] 10
  52. print(.GlobalEnv$x)
  53. # [1] 10
  54.  
  55. # result
  56. # [1] "In f"
  57. # character(0)
  58. # [1] 10
  59. # [1] "In g"
  60. # character(0)
  61. # [1] 100
  62. # <environment: 0x000000001218f368>
  63. # [1] "x"
  64. # [1] 1000
  65. # [1] "Out g"
  66. # <environment: 0x0000000012190e90>
  67. # [1] "g" "x"
  68. # [1] 100
  69. # [1] "out f"
  70. # <environment: R_GlobalEnv>
  71. # [1] "f" "x"
  72. # [1] 10
  73. # [1] 10

強制指定
利用 <<- 將會直接往上層找符合的變數改變值,故原層的不變
若到 .GlobalEnv 都沒找到,則在 .GlobalEnv 建立新變數
  1. f <- function()
  2. {
  3. print("In f")
  4. x <- list(a=10)
  5. g <- function()
  6. {
  7. print("In g")
  8. x <- list(a=1)
  9. # 直接往上層找 x,直到 .GlobalEnv
  10. x$a <<- 100
  11. print(x$a)
  12. # [1] 1
  13. print("Out g")
  14. }
  15. g()
  16. print(x$a)
  17. # [1] 100
  18. print("out f")
  19. }
  20.  
  21. x <- list(a=10)
  22. print(x$a)
  23. # [1] 10
  24.  
  25. f()
  26.  
  27. print(x$a)
  28. # [1] 100
  29.  
  30. # result
  31. # [1] 10
  32. # [1] "In f"
  33. # [1] "In g"
  34. # [1] 1
  35. # [1] "Out g"
  36. # [1] 100
  37. # [1] "out f"
  38. # [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
  1. f <- function(x)
  2. {
  3. print("In f")
  4. x$a <- 100
  5. g <- function(x)
  6. {
  7. print("In g")
  8. x$a <- 1000
  9. print(x$a)
  10. # [1] 1000
  11. print("Out g")
  12. }
  13. g(x)
  14. print(x$a)
  15. # [1] 100
  16. print("out f")
  17. }
  18.  
  19. x <- list(a=10)
  20. f(x)
  21.  
  22. print(x$a)
  23. # [1] 10
  24.  
  25. # result
  26. # [1] "In f"
  27. # [1] "In g"
  28. # [1] 1000
  29. # [1] "Out g"
  30. # [1] 100
  31. # [1] "out f"
  32. # [1] 10

替代方案
environments
每次呼叫都從設定的 env 讀值
  1. my.new.env <- new.env()
  2.  
  3. f <- function()
  4. {
  5. print("In f")
  6. my.new.env$x$a <- 100
  7. print(my.new.env$x$a)
  8. # [1] 100
  9. print("out f")
  10. }
  11.  
  12. my.new.env$x <- list(a=10)
  13. f()
  14.  
  15. print(my.new.env$x$a)
  16. # [1] 100
  17.  
  18. # result
  19. # [1] "In f"
  20. # [1] 100
  21. # [1] "out f"
  22. # [1] 100

RC(Reference class)
  1. f <- function(x)
  2. {
  3. print("In f")
  4. x$a <- 100
  5. print(x$a)
  6. # [1] 100
  7. print("out f")
  8. }
  9.  
  10. X <- setRefClass("X", fields=list(a='numeric'))
  11. x <- X(a=10)
  12. print(x$a)
  13. # [1] 10
  14.  
  15. f(x)
  16.  
  17. print(x$a)
  18. # [1] 100
  19.  
  20. # result
  21. # [1] 10
  22. # [1] "In f"
  23. # [1] 100
  24. # [1] "out f"
  25. # [1] 100

參考

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

留言