我试图了解动态分配的代码如何使用 dep 运行。
让我们以编译的Scheme程序为例。据我了解,当需要评估 lambda 表达式时,运行时必须分配内存以存储代码(实际上存储一个也有代码的闭包)。由于它无法提前知道代码的大小,所以它必须是动态的。因此,它必须为此使用堆。
为什么在尝试从堆中执行此代码时,DEP 机制没有运行时异常?
更一般地说,当 DEP 出现时,整个“代码就是数据,数据就是代码”的想法是如何发挥作用的?
我试图了解动态分配的代码如何使用 dep 运行。
让我们以编译的Scheme程序为例。据我了解,当需要评估 lambda 表达式时,运行时必须分配内存以存储代码(实际上存储一个也有代码的闭包)。由于它无法提前知道代码的大小,所以它必须是动态的。因此,它必须为此使用堆。
为什么在尝试从堆中执行此代码时,DEP 机制没有运行时异常?
更一般地说,当 DEP 出现时,整个“代码就是数据,数据就是代码”的想法是如何发挥作用的?
Lambda 表达式,或者更一般地说,“由其他函数生成和返回的函数”,看似需要动态代码生成,但实际上不需要:相反,此类函数通常由称为函数闭包的数据结构表示。
函数闭包是一对
例如,考虑以下类似 JavaScript 的代码:
function make_adder(x) {
function adder(y) {
return x + y;
}
return adder;
// equivalent to "return function(y) { return x + y; };"
}
var add42 = make_adder(42);
add42(3); // 45
当make_adder
使用参数调用时42
,它的实现返回一个闭包<adder, 42>
,它是函数和整数的对(指针)。当此闭包应用于 时,除了可见参数外,函数部分还应用于其自由变量的值。adder
42
3
42
x
3
从概念上讲,您可以认为上面的代码是这样实现的:
function make_adder(x) {
function adder(x, y) {
return x + y;
}
return { func : adder, free : x };
}
var add42 = make_adder(42);
add42.func(add42.free, 3); // 45
在 Scheme 中,第一个代码是
(define (make_adder x)
(lambda (y) (+ x y)))
(define add42 (make_adder 42))
(add42 3) ; 45
第二个是:
(define (make_adder x)
(define (adder x y)
(+ x y))
(cons adder x))
(define add42 (make_adder 42))
((car add42) (cdr add42) 3) ; 45
有关详细信息,请参阅:https://en.wikipedia.org/wiki/Closure_(computer_programming)
不,返回 lambda 不需要内存用于代码,仅用于数据/参数。考虑闭包是 OOP 中的普通对象,而创建在 Java、c# 中是“新的”...