當即執行函數 (immediately invoked function expression, IIFE) 即經過一對括號包裹一個函數體並在緊隨其後的一對括號調用此函數:html
(function () { # code goes here... })();
當即執行函數最多見的應用場景是,將局部變量的做用域限制在該函數內,以免衝突。git
例如, https://github.com/Microsoft/... 裏面也有一個 IIFE.github
這個在官方文檔 R-intro 和 R-lang 裏面都有。web
doSomething <- function() { n <- 0; return(function() { n <<- n + 1; print(n); }); }; thing <- doSomething(); thing() # [1] 1 thing() # [1] 2 thing() # [1] 3 # ...
該代碼中,函數 doSomething()
只被執行一次,並把內部的 n
設爲 0, 返回值則爲一個函數,並被咱們賦值給變量 thing
. 此後咱們每次調用 thing()
的時候,因爲 n
仍然在它全部訪問的閉包中,咱們能夠看到該值一直在被增長。express
一樣這個在官方文檔有講。segmentfault
(function() { if (TRUE) { y <- 1 }; print(y) })() # [1] 1 (function() { if (FALSE) { y <- 1 }; print(y) })() # Error in print(y) : object 'y' not found
還有,運算符 <<-
只對非局部變量賦值,若是找不到任何符合該標識符的非局部變量的話,他會在全局建立一個具備該名稱的全局變量:閉包
(function() { test <- 1; test <<- 233; print(test); })(); # [1] 1 test #[1] 233
如下示例能夠證實 R 不對 <-
變量聲明作 hoisting:ide
(function() { (function() { a <<- 1 })(); a <- 2; })(); a # [1] 1
do.call()
函數該函數在官方文檔 R-lang 有說起。此外,也能夠直接查看該函數相關文檔。函數
有的時候你會想把列表對象展開成函數的參數,但你不曉得應該怎麼辦。這個時候你須要 do.call()
:測試
do.call(what, args, quote = FALSE, envir = parent.frame())
例如:
do.call(function(x, y, z) { return(x + y + z) }, as.list(c(1, 2, 3))); # [1] 6
看到這裏,你也許會想手動實現一個通用的柯里化函數了。儘管默認並不自帶此函數,有不少庫幫咱們實現這個功能: https://cran.r-project.org/we...
然而本身實現一個其實也不是很難。
https://stackoverflow.com/que... 題目部分的內容很是優雅。
參考該 JavaScript 實現,下面給出我本身的回答。(來自前一篇文章)
Curry <- function(f, len, ...) { origList <- list(...); ret <- function(...) { cur <- c(list(...)); if (length(cur) < len) { return(function(...) { return(do.call(ret, c(cur, list(...)))); }); } return(do.call(f, cur)); }; return(do.call(ret, origList)); };
測試:
Curry(function(x, y, z) { return(x + y + z); }, 3, 2)(c(1, 2, 3))(1); # [1] 4 5 6
* 實際上還有 attach
做用域,而且隨着 detach()
終止該做用域,並且若不調用 detach()
, 甚至函數結束後被 attach()
的變量名稱還在做用域中。
在 attach()
後聲明或賦值同名變量,行爲是建立一個遮蔽被 attach 變量的變量。固然,若已存在具備該名稱的變量,則該變量會在他的做用域內,遮蔽被 attach 的變量。以上純屬我的總結,不保證正確性。。。
(function() { attach(list(some = 2333)); some <- 1; return(some); })(); # [1] 1 some # [1] 2333 detach() some # Error: object 'some' not found