函数指针、闭包和 Lambda

发布于 2024-07-07 13:58:11 字数 298 浏览 8 评论 0原文

我现在刚刚学习函数指针,当我阅读有关该主题的 K&R 章节时,我首先想到的是,“嘿,这有点像闭包。” 我知道这个假设在某种程度上从根本上是错误的,在网上搜索后我没有找到任何对此比较的分析。

那么为什么 C 风格的函数指针与闭包或 lambda 有根本的不同呢? 据我所知,这与函数指针仍然指向已定义(命名)的函数这一事实有关,而不是匿名定义函数的做法。

为什么在第二种情况下将函数传递给函数(它是未命名的)比第一种情况(它只是传递一个普通的日常函数)更强大?

请告诉我如此密切地比较两者是如何以及为什么是错误的。

I am just now learning about function pointers and, as I was reading the K&R chapter on the subject, the first thing that hit me was, "Hey, this is kinda like a closure." I knew this assumption is fundamentally wrong somehow and after a search online I didn't find really any analysis of this comparison.

So why are C-style function pointers fundamentally different from closures or lambdas? As far as I can tell it has to do with the fact that the function pointer still points to a defined (named) function as opposed to the practice of anonymously defining the function.

Why is passing a function to a function seen as more powerful in the second case, where it is unnamed, than the first where it is just a normal, everyday function that is being passed?

Please tell me how and why I am wrong to compare the two so closely.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

提笔落墨 2024-07-14 13:58:11

lambda(或闭包)封装了函数指针和变量。 这就是为什么在 C# 中,您可以这样做:

int lessThan = 100;
Func<int, bool> lessThanTest = delegate(int i) {
   return i < lessThan;
};

我在那里使用了一个匿名委托作为闭包(它的语法比等效的 lambda 更清晰、更接近 C),它将 lessThan(堆栈变量)捕获到闭包中。 当闭包被评估时,lessThan(其堆栈帧可能已被破坏)将继续被引用。 如果我更改 lessThan,那么我会更改比较:

int lessThan = 100;
Func<int, bool> lessThanTest = delegate(int i) {
   return i < lessThan;
};

lessThanTest(99); // returns true
lessThan = 10;
lessThanTest(99); // returns false

在 C 中,这是非法的:

BOOL (*lessThanTest)(int);
int lessThan = 100;

lessThanTest = &LessThan;

BOOL LessThan(int i) {
   return i < lessThan; // compile error - lessThan is not in scope
}

虽然我可以定义一个带有 2 个参数的函数指针:

int lessThan = 100;
BOOL (*lessThanTest)(int, int);

lessThanTest = &LessThan;
lessThanTest(99, lessThan); // returns true
lessThan = 10;
lessThanTest(100, lessThan); // returns false

BOOL LessThan(int i, int lessThan) {
   return i < lessThan;
}

但是,现在我在评估它时必须传递 2 个参数。 如果我希望将此函数指针传递给 lessThan 不在范围内的另一个函数,我要么必须通过将其传递给链中的每个函数来手动保持其活动状态,要么将其提升为全局函数。

尽管大多数支持闭包的主流语言都使用匿名函数,但对此没有要求。 你可以有没有匿名函数的闭包,也可以有没有闭包的匿名函数。

总结:闭包是函数指针+捕获变量的组合。

A lambda (or closure) encapsulates both the function pointer and variables. This is why, in C#, you can do:

int lessThan = 100;
Func<int, bool> lessThanTest = delegate(int i) {
   return i < lessThan;
};

I used an anonymous delegate there as a closure (it's syntax is a little clearer and closer to C than the lambda equivalent), which captured lessThan (a stack variable) into the closure. When the closure is evaluated, lessThan (whose stack frame may have been destroyed) will continue to be referenced. If I change lessThan, then I change the comparison:

int lessThan = 100;
Func<int, bool> lessThanTest = delegate(int i) {
   return i < lessThan;
};

lessThanTest(99); // returns true
lessThan = 10;
lessThanTest(99); // returns false

In C, this would be illegal:

BOOL (*lessThanTest)(int);
int lessThan = 100;

lessThanTest = &LessThan;

BOOL LessThan(int i) {
   return i < lessThan; // compile error - lessThan is not in scope
}

though I could define a function pointer that takes 2 arguments:

int lessThan = 100;
BOOL (*lessThanTest)(int, int);

lessThanTest = &LessThan;
lessThanTest(99, lessThan); // returns true
lessThan = 10;
lessThanTest(100, lessThan); // returns false

BOOL LessThan(int i, int lessThan) {
   return i < lessThan;
}

But, now I have to pass the 2 arguments when I evaluate it. If I wished to pass this function pointer to another function where lessThan was not in scope, I would either have to manually keep it alive by passing it to each function in the chain, or by promoting it to a global.

Though most mainstream languages that support closures use anonymous functions, there is no requirement for that. You can have closures without anonymous functions, and anonymous functions without closures.

Summary: a closure is a combination of function pointer + captured variables.

笑饮青盏花 2024-07-14 13:58:11

作为为带有和不带有“真正”闭包的语言编写过编译器的人,我非常不同意上面的一些答案。 Lisp、Scheme、ML 或 Haskell 闭包不会动态创建新函数。 相反,它重用现有函数,但使用新的自由变量。 自由变量的集合通常被称为环境,至少编程语言理论家是如此。

闭包只是包含函数和环境的聚合。 在新泽西州标准机器学习编译器中,我们将一个表示为一条记录; 一个字段包含指向代码的指针,其他字段包含自由变量的值。 编译器通过分配一个包含指向相同代码的指针的新记录动态地创建了一个新的闭包(而不是函数),但具有不同的值自由变量。

你可以用 C 语言模拟所有这些,但这是一件很痛苦的事情。 有两种技术很流行:

  1. 传递一个指向函数(代码)的指针和一个指向自由变量的单独指针,以便将闭包拆分为两个 C 变量。

  2. 传递一个指向结构的指针,其中该结构包含自由变量的值以及指向代码的指针。

    传递

当您尝试在 C 中模拟某种多态并且您不想透露环境的类型时,技术 #1 是理想的选择——您使用 void* 指针来表示环境。 例如,请查看 Dave Hanson 的 C 接口和实现。 技术 #2 更类似于函数式语言的本机代码编译器中发生的情况,也类似于另一种熟悉的技术……具有虚拟成员函数的 C++ 对象。 实现几乎相同。

这一观察引出了亨利·贝克的俏皮话:

Algol/Fortran 世界的人们多年来一直抱怨他们不明白函数闭包在未来的高效编程中可能有什么用途。 然后“面向对象编程”革命发生了,现在每个人都使用函数闭包进行编程,只是他们仍然拒绝这样称呼它们。

As someone who has written compilers for languages both with and without 'real' closures, I respectfully disagree with some of the answers above. A Lisp, Scheme, ML, or Haskell closure does not create a new function dynamically. Instead it reuses an existing function but does so with new free variables. The collection of free variables is often called the environment, at least by programming-language theorists.

A closure is just an aggregate containing a function and an environment. In the Standard ML of New Jersey compiler, we represented one as a record; one field contained a pointer to the code, and the other fields contained the values of the free variables. The compiler created a new closure (not function) dynamically by allocating a new record containing a pointer to the same code, but with different values for the free variables.

You can simulate all this in C, but it is a pain in the ass. Two techniques are popular:

  1. Pass a pointer to the function (the code) and a separate pointer to the free variables, so that the closure is split across two C variables.

  2. Pass a pointer to a struct, where the struct contains the values of the free variables and also a pointer to the code.

Technique #1 is ideal when you are trying to simulate some kind of polymorphism in C and you don't want to reveal the type of the environment---you use a void* pointer to represent the environment. For examples, look at Dave Hanson's C Interfaces and Implementations. Technique #2, which more closely resembles what happens in native-code compilers for functional languages, also resembles another familiar technique... C++ objects with virtual member functions. The implementations are almost identical.

This observation led to a wisecrack from Henry Baker:

People in the Algol/Fortran world complained for years that they didn't understand what possible use function closures would have in efficient programming of the future. Then the `object oriented programming' revolution happened, and now everyone programs using function closures, except that they still refuse to to call them that.

蒗幽 2024-07-14 13:58:11

在 C 中,您无法内联定义函数,因此您无法真正创建闭包。 您所做的只是传递对某些预定义方法的引用。 在支持匿名方法/闭包的语言中,方法的定义要灵活得多。

用最简单的术语来说,函数指针没有与之关联的作用域(除非计算全局作用域),而闭包则包括定义它们的方法的作用域。 使用 lambda,您可以编写一个方法来编写一个方法。 闭包允许您将“一些参数绑定到一个函数并获得一个较低数量的函数作为结果”。 (摘自托马斯的评论)。 你不能在 C 中这样做。

编辑:添加一个示例(我将使用 Actionscript-ish 语法,因为这就是我现在的想法):

假设你有一些方法采用另一个方法作为其参数,但不没有提供一种在调用该方法时将任何参数传递给该方法的方法吗? 比如,某些方法在运行您传递给它的方法之前会导致延迟(愚蠢的例子,但我想保持简单)。

function runLater(f:Function):Void {
  sleep(100);
  f();
}

现在假设您希望使用 runLater() 来延迟对象的某些处理:

function objectProcessor(o:Object):Void {
  /* Do something cool with the object! */
}

function process(o:Object):Void {
  runLater(function() { objectProcessor(o); });
}

您传递给 process() 的函数不再是静态定义的函数。 它是动态生成的,并且能够包含对定义方法时范围内的变量的引用。 因此,它可以访问“o”和“objectProcessor”,即使它们不在全局范围内。

我希望这是有道理的。

In C you can't define the function inline, so you can't really create a closure. All you're doing is passing around a reference to some pre-defined method. In languages that support anonymous methods/closures, the definition of the methods are a lot more flexible.

In the simplest terms, function pointers have no scope associated with them (unless you count the global scope), whereas closures include the scope of the method that's defining them. With lambdas, you can write a method that writes a method. Closures allow you to bind "some arguments to a function and getting a lower-arity function as a result." (taken from Thomas's comment). You can't do that in C.

EDIT: Adding an example (I'm going to use Actionscript-ish syntax cause that's what's on my mind right now):

Say you have some method that takes another method as its argument, but doesn't provide a way to pass any parameters to that method when it's called? Like, say, some method that causes a delay before running the method you passed it (stupid example, but I want to keep it simple).

function runLater(f:Function):Void {
  sleep(100);
  f();
}

Now say you want to user runLater() to delay some processing of an object:

function objectProcessor(o:Object):Void {
  /* Do something cool with the object! */
}

function process(o:Object):Void {
  runLater(function() { objectProcessor(o); });
}

The function you're passing to process() isn't some staticly defined function anymore. It's dynamically generated, and is able to include references to variables that were in scope when the method was defined. So, it can access 'o' and 'objectProcessor', even though those aren't in the global scope.

I hope that made sense.

隐诗 2024-07-14 13:58:11

封闭=逻辑+环境。

例如,考虑这个 C# 3 方法:

public Person FindPerson(IEnumerable<Person> people, string name)
{
    return people.Where(person => person.Name == name);
}

lambda 表达式不仅封装了逻辑(“比较名称”),而且还封装了环境,包括参数(即局部变量)“名称”。

有关这方面的更多信息,请参阅我的有关闭包的文章,该文章将带您了解 C# 1 、2 和 3,展示了闭包如何让事情变得更容易。

Closure = logic + environment.

For instance, consider this C# 3 method:

public Person FindPerson(IEnumerable<Person> people, string name)
{
    return people.Where(person => person.Name == name);
}

The lambda expression not only encapsulates the logic ("compare the name") but also the environment, including the parameter (i.e. local variable) "name".

For more on this, have a look at my article on closures which takes you through C# 1, 2 and 3, showing how closures make things easier.

苦行僧 2024-07-14 13:58:11

在 C 中,函数指针可以作为参数传递给函数,并作为函数的值返回,但函数仅存在于顶层:不能相互嵌套函数定义。 考虑一下 C 需要如何支持可以访问外部函数的变量的嵌套函数,同时仍然能够在调用堆栈中上下发送函数指针。 (要遵循此说明,您应该了解如何在 C 和大多数类似语言中实现函数调用的基础知识:浏览 维基百科上的调用堆栈条目。)指向

嵌套函数的指针是什么样的对象? 它不能只是代码的地址,因为如果你调用它,它如何访问外部函数的变量? (请记住,由于递归,可能会同时对外部函数进行多个不同的调用。)这称为 funargs 问题,并且有两个子问题:向下的 funargs 问题和向上的 funargs 问题。

向下 funargs 问题,即,将函数指针“向下”发送到您调用的函数的参数,实际上与 C 和 GCC 不兼容 支持 嵌套函数作为向下的 funargs。 在 GCC 中,当您创建指向嵌套函数的指针时,您实际上获得了一个指向 的指针trampoline,一段动态构造的代码,设置静态链接指针,然后调用实际函数,该函数使用静态链接指针访问变量的外层函数。

向上的 funargs 问题更加困难。 GCC 不会阻止您在外部函数不再活动(调用堆栈上没有记录)后让蹦床指针存在,然后静态链接指针可能指向垃圾。 激活记录不能再分配在堆栈上。 通常的解决方案是将它们分配在堆上,并让代表嵌套函数的函数对象仅指向外部函数的激活记录。 这样的对象称为闭包。 那么该语言通常必须支持垃圾收集,以便记录可以一旦不再有指针指向它们就被释放。

Lambda(匿名函数)实际上是一个单独的问题,但通常是一种允许您定义匿名的语言动态函数还允许您将它们作为函数值返回,因此它们最终会成为闭包。

In C, function pointers can be passed as arguments to functions and returned as values from functions, but functions exist only at top level: you cannot nest function definitions within each other. Think about what it would take for C to support nested functions that can access the variables of the outer function, while still being able to send function pointers up and down the call stack. (To follow this explanation, you should know the basics of how function calls are implemented in C and most similar languages: browse through the call stack entry on Wikipedia.)

What kind of object is a pointer to a nested function? It cannot just be the address of the code, because if you call it, how does it access the variables of the outer function? (Remember that because of recursion, there may be several different calls of the outer function active at one time.) This is called the funarg problem, and there are two subproblems: the downward funargs problem and the upwards funargs problem.

The downwards funargs problem, i.e., sending a function pointer "down the stack" as an argument to a function you call, is actually not incompatible with C, and GCC supports nested functions as downward funargs. In GCC, when you create a pointer to a nested function, you really get a pointer to a trampoline, a dynamically constructed piece of code that sets up the static link pointer and then calls the real function, which uses the static link pointer to access the variables of the outer function.

The upwards funargs problem is more difficult. GCC does not prevent you from letting a trampoline pointer exist after the outer function is no longer active (has no record on the call stack), and then the static link pointer could point to garbage. Activation records can no longer be allocated on a stack. The usual solution is to allocate them on the heap, and let a function object representing a nested function just point to the activation record of the outer function. Such an object is called a closure. Then the language will typically have to support garbage collection so that the records can be freed once there are no more pointers pointing to them.

Lambdas (anonymous functions) are really a separate issue, but usually a language that lets you define anonymous functions on the fly will also let you return them as function values, so they end up being closures.

夜唯美灬不弃 2024-07-14 13:58:11

lambda 是一个匿名的、动态定义的函数。 你只是不能在 C 中做到这一点......至于闭包(或两者的结合),典型的 lisp 示例看起来类似于:

(defun get-counter (n-start +-number)
     "Returns a function that returns a number incremented
      by +-number every time it is called"
    (lambda () (setf n-start (+ +-number n-start))))

在 C 术语中,你可以说词法环境(堆栈) get-counter 被匿名函数捕获,并在内部进行修改,如下例所示:

[1]> (defun get-counter (n-start +-number)
         "Returns a function that returns a number incremented
          by +-number every time it is called"
        (lambda () (setf n-start (+ +-number n-start))))
GET-COUNTER
[2]> (defvar x (get-counter 2 3))
X
[3]> (funcall x)
5
[4]> (funcall x)
8
[5]> (funcall x)
11
[6]> (funcall x)
14
[7]> (funcall x)
17
[8]> (funcall x)
20
[9]> 

A lambda is an anonymous, dynamically defined function. You just cannot do that in C... as for closures (or the convination of the two), the typical lisp example would look something along the lines of:

(defun get-counter (n-start +-number)
     "Returns a function that returns a number incremented
      by +-number every time it is called"
    (lambda () (setf n-start (+ +-number n-start))))

In C terms, you could say that the lexical environment (the stack) of get-counter is being captured by the anonymous function, and modified internally as the following example shows:

[1]> (defun get-counter (n-start +-number)
         "Returns a function that returns a number incremented
          by +-number every time it is called"
        (lambda () (setf n-start (+ +-number n-start))))
GET-COUNTER
[2]> (defvar x (get-counter 2 3))
X
[3]> (funcall x)
5
[4]> (funcall x)
8
[5]> (funcall x)
11
[6]> (funcall x)
14
[7]> (funcall x)
17
[8]> (funcall x)
20
[9]> 
¢蛋碎的人ぎ生 2024-07-14 13:58:11

闭包意味着从函数定义的角度来看,某些变量与函数逻辑绑定在一起,就像能够动态声明一个迷你对象一样。

C 和闭包的一个重要问题是,在堆栈上分配的变量在离开当前作用域时将被销毁,无论闭包是否指向它们。 这会导致人们在不小心返回指向局部变量的指针时遇到的错误。 闭包基本上意味着所有相关变量要么是堆上的引用计数项,要么是垃圾收集项。

我不太愿意将 lambda 与闭包等同起来,因为我不确定所有语言中的 lambda 都是闭包,有时我认为 lambda 只是本地定义的匿名函数,没有绑定变量(Python 2.1 之前的版本?)。

Closures imply some variable from the point of function definition is bound together with the function logic, like being able to declare a mini-object on the fly.

One important problem with C and closures is variables allocated on the stack will be destroyed on leaving the current scope, regardless of if a closure was pointing to them. This would lead to the kind of bugs people get when they carelessly return pointers to local variables. Closures basically imply all relevant variables are either ref-counted or garbage-collected items on a heap.

I'm not comfortable equating lambda with closure because I'm not sure that lambdas in all languages are closures, at times I think lambdas have just been locally defined anonymous functions without the binding of variables (Python pre 2.1?).

抚笙 2024-07-14 13:58:11

在 GCC 中,可以使用以下宏来模拟 lambda 函数:

#define lambda(l_ret_type, l_arguments, l_body)       \
({                                                    \
    l_ret_type l_anonymous_functions_name l_arguments \
    l_body                                            \
    &l_anonymous_functions_name;                      \
})

source

qsort (array, sizeof (array) / sizeof (array[0]), sizeof (array[0]),
     lambda (int, (const void *a, const void *b),
             {
               dump ();
               printf ("Comparison %d: %d and %d\n",
                       ++ comparison, *(const int *) a, *(const int *) b);
               return *(const int *) a - *(const int *) b;
             }));

使用这种技术当然会消除您的应用程序与其他编译器一起工作的可能性,并且显然是“未定义”行为,所以 YMMV。

In GCC it is possible to simulate lambda functions using the following macro:

#define lambda(l_ret_type, l_arguments, l_body)       \
({                                                    \
    l_ret_type l_anonymous_functions_name l_arguments \
    l_body                                            \
    &l_anonymous_functions_name;                      \
})

Example from source:

qsort (array, sizeof (array) / sizeof (array[0]), sizeof (array[0]),
     lambda (int, (const void *a, const void *b),
             {
               dump ();
               printf ("Comparison %d: %d and %d\n",
                       ++ comparison, *(const int *) a, *(const int *) b);
               return *(const int *) a - *(const int *) b;
             }));

Using this technique of course removes the possibility of your application working with other compilers and is apparently "undefined" behavior so YMMV.

匿名的好友 2024-07-14 13:58:11

闭包捕获环境中的自由变量。 即使周围的代码可能不再活跃,环境仍然存在。

Common Lisp 中的一个示例,其中 MAKE-ADDER 返回一个新的闭包。

CL-USER 53 > (defun make-adder (start delta) (lambda () (incf start delta)))
MAKE-ADDER

CL-USER 54 > (compile *)
MAKE-ADDER
NIL
NIL

使用上述函数:

CL-USER 55 > (let ((adder1 (make-adder 0 10))
                   (adder2 (make-adder 17 20)))
               (print (funcall adder1))
               (print (funcall adder1))
               (print (funcall adder1))
               (print (funcall adder1))
               (print (funcall adder2))
               (print (funcall adder2))
               (print (funcall adder2))
               (print (funcall adder1))
               (print (funcall adder1))
               (describe adder1)
               (describe adder2)
               (values))

10 
20 
30 
40 
37 
57 
77 
50 
60 
#<Closure 1 subfunction of MAKE-ADDER 4060001ED4> is a CLOSURE
Function         #<Function 1 subfunction of MAKE-ADDER 4060001CAC>
Environment      #(60 10)
#<Closure 1 subfunction of MAKE-ADDER 4060001EFC> is a CLOSURE
Function         #<Function 1 subfunction of MAKE-ADDER 4060001CAC>
Environment      #(77 20)

请注意,DESCRIBE 函数显示两个闭包函数对象是相同的,但是环境< /em> 是不同的。

Common Lisp 使闭包和纯函数对象(没有环境的对象)都成为函数,并且可以用相同的方式调用两者,这里使用 FUNCALL

The closure captures the free variables in an environment. The environment will still exist, even though the surrounding code may no longer be active.

An example in Common Lisp, where MAKE-ADDER returns a new closure.

CL-USER 53 > (defun make-adder (start delta) (lambda () (incf start delta)))
MAKE-ADDER

CL-USER 54 > (compile *)
MAKE-ADDER
NIL
NIL

Using the above function:

CL-USER 55 > (let ((adder1 (make-adder 0 10))
                   (adder2 (make-adder 17 20)))
               (print (funcall adder1))
               (print (funcall adder1))
               (print (funcall adder1))
               (print (funcall adder1))
               (print (funcall adder2))
               (print (funcall adder2))
               (print (funcall adder2))
               (print (funcall adder1))
               (print (funcall adder1))
               (describe adder1)
               (describe adder2)
               (values))

10 
20 
30 
40 
37 
57 
77 
50 
60 
#<Closure 1 subfunction of MAKE-ADDER 4060001ED4> is a CLOSURE
Function         #<Function 1 subfunction of MAKE-ADDER 4060001CAC>
Environment      #(60 10)
#<Closure 1 subfunction of MAKE-ADDER 4060001EFC> is a CLOSURE
Function         #<Function 1 subfunction of MAKE-ADDER 4060001CAC>
Environment      #(77 20)

Note that the DESCRIBE function shows that the function objects for both closures are the same, but the environment is different.

Common Lisp makes both closures and pure function objects (those without an environment) both to be functions and one can call both in the same way, here using FUNCALL.

ゞ记忆︶ㄣ 2024-07-14 13:58:11

主要区别在于 C 中缺乏词法作用域。

函数指针就是指向代码块的指针。 它引用的任何非堆栈变量都是全局的、静态的或类似的。

闭包 OTOH 有其自己的状态,形式为“外部变量”或“upvalues”。 使用词法作用域,它们可以是私有的,也可以是共享的。 您可以使用相同的函数代码但不同的变量实例创建大量闭包。

一些闭包可以共享一些变量,因此可以共享对象的接口(在 OOP 意义上)。 为了在 C 中做到这一点,你必须将一个结构与一个函数指针表关联起来(这就是 C++ 所做的,与一个类 vtable)。

简而言之,闭包是一个函数指针加上一些状态。 这是一个更高层次的构造

The main difference arises from the lack of lexical scoping in C.

A function pointer is just that, a pointer to a block of code. Any non-stack variable that it references is global, static or similar.

A closure, OTOH, has its own state in the form of 'outer variables', or 'upvalues'. they can be as private or shared as you want, using lexical scoping. You can create lots of closures with the same function code, but different variables instances.

A few closures can share some variables, and so can be the interface of an object (in the OOP sense). to make that in C you have to associate a structure with a table of function pointers (that's what C++ does, with a class vtable).

in short, a closure is a function pointer PLUS some state. it's a higher-level construct

栀子花开つ 2024-07-14 13:58:11

大多数响应表明闭包需要函数指针,可能指向匿名函数,但正如 Mark 所写 闭包可以与命名函数一起存在。 下面是 Perl 中的一个示例:

{
    my $count;
    sub increment { return $count++ }
}

闭包是定义 $count 变量的环境。 它仅适用于 increment 子例程,并且在调用之间持续存在。

Most of the responses indicate that closures require function pointers, possibly to anonymous functions, but as Mark wrote closures can exist with named functions. Here's an example in Perl:

{
    my $count;
    sub increment { return $count++ }
}

The closure is the environment that defines the $count variable. It is only available to the increment subroutine and persists between calls.

一绘本一梦想 2024-07-14 13:58:11

最大的问题是:幕后的闭包和/或 lambda 是什么? 它会变成什么闭包和/或 lambda 甚至更多,一个委托? 非常可能的答案是,它们成为一种函数指针作为汇编代码,因此,闭包、委托、lambda、匿名函数本质上是一种以高级方式声明/定义函数指针的糖语法,但这种声明包括一些定义环境变量范围的机制。

The big question is: what is a closure and/or lambda behind the scenes? what does it become a closure and/or a lambda or even more, a delegate? the very possible answer is that these become in a sort of function pointer as assembly code, thus, closures, delegates, lambdas, anonymous functions are in essence a kind of sugar syntax to declare/define function pointers in a high level way but this declarations includes some mechanism to define some scope to environment variables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文