如何用简单的英语解释回调?它们与从一个函数调用另一个函数从调用函数获取上下文有什么不同?如何向新手程序员解释它们的强大功能?


当前回答

在PHP中,它是这样的:

<?php

function string($string, $callback) {
     $results = array(
        'upper' => strtoupper($string),
        'lower' => strtolower($string),
        );

    if(is_callable($callback)) {
        call_user_func($callback, $results);
    }
}

string('Alex', function($name) {
    echo $name['lower'];
});

其他回答

想象一下,一个朋友要离开你的家,你告诉她“到家后给我打个电话,好让我知道你已经安全到家了”;这是(字面上的)回电。这就是回调函数,与语言无关。您希望某个过程在完成某些任务后将控制传递回给您,因此您可以给它一个函数,用于回调。

例如,在Python中,

grabDBValue( (lambda x: passValueToGUIWindow(x) ))

grabDBValue可以被编写为只从数据库获取一个值,然后让您指定对该值实际做什么,因此它接受一个函数。您不知道grabDBValue何时或是否会返回,但是如果/当它返回时,您知道希望它做什么。在这里,我传入一个匿名函数(或lambda),它将值发送到GUI窗口。我可以通过这样做轻松地改变程序的行为:

grabDBValue( (lambda x: passToLogger(x) ))

回调在函数是第一类值的语言中工作得很好,就像通常的整数、字符串、布尔值等。在C语言中,你可以通过传递指向函数的指针来“传递”函数,调用者可以使用它;在Java中,调用者将请求具有特定方法名的特定类型的静态类,因为类之外没有函数(实际上是“方法”);在大多数其他动态语言中,您可以通过简单的语法传递函数。

Protip:

在具有词法作用域的语言(如Scheme或Perl)中,您可以使用这样的技巧:

my $var = 2;
my $val = someCallerBackFunction(sub callback { return $var * 3; });
# Perlistas note: I know the sub doesn't need a name, this is for illustration

在本例中$val将为6,因为回调可以访问定义它的词法环境中声明的变量。词法作用域和匿名回调是一个强大的组合,值得新手进一步研究。

回调是在满足条件时被计划执行的方法。

一个“真实世界”的例子是当地的电子游戏商店。你在等待《半条命3》。你不必每天去商店查看游戏是否上架,而是在列表中注册电子邮件,以便在游戏上架时收到通知。这封邮件变成了你的“回调”,你需要满足的条件是游戏的可用性。

“程序员”的例子是一个网页,你想在点击按钮时执行一个操作。为按钮注册回调方法,然后继续执行其他任务。当/如果用户点击按钮,浏览器将查看该事件的回调列表并调用您的方法。

回调是一种异步处理事件的方法。你永远不知道回调什么时候会被执行,或者它是否会被执行。这样做的好处是可以释放程序和CPU周期,以便在等待应答时执行其他任务。

隐喻性的解释:

我有一个包裹要寄给一个朋友,我也想知道我的朋友什么时候收到。

所以我把包裹带到邮局,让他们把它送到。如果我想知道我的朋友什么时候收到包裹,我有两个选择:

我可以在邮局等邮件送到。

(b)邮件送达后我会收到电子邮件。

选项(b)类似于回调。

A callback is a function that will be called by a second function. This second function doesn't know in advance what function it will call. So the identity of the callback function is stored somewhere, or passed to the second function as a parameter. This "identity," depending on the programming language, might be the address of the callback, or some other sort of pointer, or it might be the name of the function. The principal is the same, we store or pass some information that unambiguously identifies the function.

当时间到来时,第二个函数可以调用回调,根据当时的情况提供参数。它甚至可以从一组可能的回调中选择回调。编程语言必须提供某种语法,允许第二个函数调用回调函数,并知道它的“标识”。

这种机制有许多可能的用途。通过回调,函数的设计者可以通过调用所提供的任何回调来定制函数。例如,排序函数可能将回调函数作为参数,而这个回调函数可能是用于比较两个元素以决定哪个元素先出现的函数。

顺便说一下,根据编程语言的不同,上面讨论中的“函数”一词可能会被“块”、“闭包”、“lambda”等取代。

简单明了:回调是你给另一个函数的函数,这样它就可以调用它。

通常在某个操作完成时调用它。由于在将回调函数交给其他函数之前创建了回调,因此可以使用调用站点的上下文信息初始化它。这就是为什么它被命名为call*back* -第一个函数从它被调用的地方回调到上下文。