r - 如果一个函数是在另一个函数中创建的,那么函数常量存储在哪里?
问题描述
我正在使用父函数通过在父函数调用中返回函数来生成子函数。父函数的目的是在子函数中设置一个常数(y)。下面是一个MWE。当我尝试调试子函数时,我无法弄清楚变量存储在哪个环境中。
power=function(y){
return(function(x){return(x^y)})
}
square=power(2)
debug(square)
square(3)
debugging in: square(3)
debug at #2: {
return(x^y)
}
Browse[2]> x
[1] 3
Browse[2]> y
[1] 2
Browse[2]> ls()
[1] "x"
Browse[2]> find('y')
character(0)
解决方案
如果您检查 R 函数的类型,您将观察到以下内容:
> typeof(square)
[1] "closure"
实际上,这正是您问题的答案:闭包是一个在.
R 还告诉你这是哪个环境(尽管不是非常有用):
> square
function(x){return(x^y)}
<environment: 0x7ffd9218e578>
(每次运行的确切数字会有所不同——它只是一个内存地址。)
现在,这对应于哪个环境?它对应于我们执行时创建的本地环境power(2)
(“<a href="https://en.wikipedia.org/wiki/Call_stack#Stack_and_frame_pointers" rel="noreferrer">堆栈帧”)。正如另一个答案所说,它现在是square
函数的父环境(实际上,在 R 中,除了某些内置函数之外,每个函数都与父环境相关联):
> ls(environment(square))
[1] "y"
> environment(square)$y
[1] 2
您可以在Hadley 的Advanced R book的章节中阅读有关环境的更多信息。
顺便说一句,闭包是函数式编程语言的核心特性。函数式语言的另一个核心特征是每个表达式都是一个值 ——并且,隐含地,函数的(返回)值是其最后一个表达式的值。这意味着return
在 R 中使用该函数既不必要又具有误导性!1因此,您应该忽略它:这会产生更短、更易读的代码:
power = function (y) {
function (x) x ^ y
}
这里还有另一个特定于 R 的微妙之处:由于参数是惰性求值的,因此您的函数定义容易出错:
> two = 2
> square = power(two)
> two = 10
> square(5)
[1] 9765625
哎呀!变量的后续修改two
反映在内部square
(但只是第一次!进一步的重新定义不会改变任何东西)。为了防止这种情况,请使用以下force
功能:
power = function (y) {
force(y)
function (x) x ^ y
}
force
只是强制评估参数名称,仅此而已。
1具有误导性,因为return
它是 R 中的一个函数,与过程语言相比,它的含义略有不同:它会中止当前函数的执行。
推荐阅读
- jpa - createQuery 和 createNativeQuery JPA 之间的性能差异
- mule - 如何在 Dataweave 2.0 中压缩和嵌套 (CSV) 有效负载?
- php - 可拖动的图像滑块
- reactjs - Deno Oak 禁用 Cors
- javascript - 当我运行命令服务时,我得到无效的标记压缩接近堆限制分配失败 - JavaScript 堆内存不足错误
- xml - XSLT 和 XML 生成中的串联
- javascript - 如何让这个积极的后向正则表达式在 Safari 中运行
- node.js - 在 azure 管道中运行的 javascript 中检索 COSMOS 连接字符串或主键
- wordpress - 如何将 wordpress 博客添加到 angular8 网站?
- python - 排列函数