关于 R 语言,你很可能也想了解对这 5 个问题的解答

尾调潮涌
• 阅读 3081

1. 立即执行函数

立即执行函数 (immediately invoked function expression, IIFE) 即通过一对括号包裹一个函数体并在紧随其后的一对括号调用此函数:

(function () {
    # code goes here...
})();

立即执行函数最常见的应用场景是,将局部变量的作用域限制在该函数内,以避免冲突。

例如, https://github.com/Microsoft/... 里面也有一个 IIFE.

2. 闭包与私有变量

这个在官方文档 R-intro 和 R-lang 里面都有。

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 仍然在它所有访问的闭包中,我们可以看到该值一直在被增加。

3. 变量具有函数作用域*,但是不被提升

同样这个在官方文档有讲。

(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:

(function() { (function() { a <<- 1 })(); a <- 2; })();
a # [1] 1

4. 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

5. 函数柯里化

看到这里,你也许会想手动实现一个通用的柯里化函数了。尽管默认并不自带此函数,有很多库帮我们实现这个功能: 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
点赞
收藏
评论区
推荐文章
Jacquelyn38 Jacquelyn38
4年前
从Vue.js源码中我学到了尤大大几点精妙方法
话不多说,赶快试试尤大大教给我们的这几个精妙方法吧!在工作中肯定会用得到。立即执行函数页面加载完成后只执行一次的设置函数。(function (a, b)  console.log(a, b); // 1,2)(1, 2);通常,全局变量被作为一个参数传递给立即执行参数,这样它在函数内部不使用window也可以被访问到。(function (g
Stella981 Stella981
3年前
JS中!function(){}()的理解
这种写法,是一种立即执行函数的写法,即IIFE等设计模式。这种函数在函数定义的地方就直接执行了。理解IIFE设计模式的关键是要认识到,在ES6之前,JavaScript仅具有函数作用域(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fen.wikipedia.org%2Fwiki
Wesley13 Wesley13
3年前
C语言
主函数程序的入口main函数不可没有,也不可出现多行main函数,main有且仅有一个。intmain()return0main前面的int指的是函数调用后返回一个整型值。int是整形。返回0,0是整数voidmain是过时的函数。库函数C语言本身提供给我们使用的函数。数据类型:char字符型
Stella981 Stella981
3年前
ES6中Generator理解
1\.生成器函数声明  function\ name(args){};2\.yield使用function hello(){    console.log('before hello');  //可看到hello()并不会立刻执行函数, 到第一次next调用时才会    var name 
Stella981 Stella981
3年前
JS 对象数组Array 根据对象object key的值排序sort,很风骚哦
有个js对象数组varary\{id:1,name:"b"},{id:2,name:"b"}\需求是根据name或者id的值来排序,这里有个风骚的函数函数定义:function keysrt(key,desc) {  return function(a,b){    return desc ? ~~(ak
Stella981 Stella981
3年前
JS 中的this指向问题和call、apply、bind的区别
this的指向问题一般情况下this对象指向调用函数的对象,全局环境中执行函数this对象指向window。functiona(){console.log(this);//输出函数a中的this对象}functionb(){};varc{name:"call"}
Wesley13 Wesley13
3年前
Mysql自定义函数(function)
语法自定义函数也需要相应的要求,语法如下:_CREATEFUNCTION__<函数名称(参数列表)__RETURNS返回值类型_  函数体删除:_DROP__FUNCTION <函数名称_调用自定义函数语法:_SELECT <函数名称(paramet
Stella981 Stella981
3年前
Javascript技巧
匿名立即执行函数1//匿名立即执行函数
Wesley13 Wesley13
3年前
VC++知识点整理
1.内联函数定义:定义在类体内的成员函数,即函数的函数体放在类体内特点:在调用处用内联函数体的代码来替换,用于解决程序的运行效率问题。一定要在调用之前定义,并且内联函数无法递归调用。2.构造函数与析构函数构造函数:用于为对象分配内存空间,对类的成员变量进行初始化,并执行其他内部管理操作。可以接受参
小万哥 小万哥
1年前
Go 语言函数、参数和返回值详解
函数是一组语句,可以在程序中重复使用。函数不会在页面加载时自动执行。函数将通过调用函数来执行。创建函数要创建(通常称为声明)一个函数,请执行以下操作:使用func关键字。指定函数的名称,后跟括号()。最后,在花括号内添加定义函数应执行的代码。语法Gofun
小万哥 小万哥
1年前
C 语言函数:入门指南
C语言中的函数声明和定义您可以通过以下方式创建并调用函数:c//创建一个函数voidmyFunction()printf("我刚被执行了!");intmain()myFunction();//调用函数return0;一个函数包括两个部分:声明:函数名称、返
尾调潮涌
尾调潮涌
Lv1
因为给不了你要的所以放开了手让你远走。
文章
7
粉丝
0
获赞
0