Lambda函数

4
我非常感兴趣了解lambda函数的使用。在像php这样的现代高级编程语言中使用它们是否有意义?如果是,为什么呢?
这真的只是一个嵌套在函数内部的函数(就像这个)还是背后有更多东西?

1
@Donal:感谢你的合并,我本来想做的,但刷新了编辑历史记录后发现你已经完成了。(我们真的需要一些技术措施来帮助解决这个问题。) - Roger Pate
@Roger:同意。有时候我在进行长时间编辑时,会收到一个顶部通知,表示有些东西发生了变化,但这并不等同于两个人同时进行短期修改时的情况;他们只是相互冲突。 - Donal Fellows
5个回答

7

一个 lambda 表达式表示一个函数作为一个值。它可以像一个值一样被传递(因为它就是一个值),但是通过给它一些参数来应用它。命名函数只是映射到 lambda 表达式的名称,无论是常量还是变量(取决于语言细节)。

而且,在高级编程语言中它们非常普遍。例如,在 JavaScript 中所有的函数实际上都是存储在变量中的 lambda 表达式。


5
一个lambda函数是一个对象(或值)。它可以作为参数传递给另一个函数,或从另一个函数返回。
map(lambda x: x**2, [1,2,3,4])

它不需要名字; 当你使用(例如在Python中)lambda x:x ** 2创建一个时,你就有了lambda函数。与传统方法相比,这是一个对比:
def square(x):
    return x**2

也许最重要的是,您可以在运行时构建它们。
def make_exp_function(n):
    return lambda x: x**n

square = make_exp_function(2)
cube = make_exp_function(3)
for i in range(100):
    f = make_exp_function(i)
    print f(2)

我必须补充一下,这是一个被低估的重要点。 这意味着你可以以比 EVAL 更加可控和高效的方式动态创建代码。 它使得像抽象工厂这样的编程变得更加容易。 - MER

5

虽然PHP支持匿名函数,但它们实际上并不是闭包--因此你会错过最有趣的部分。

在JavaScript(以及支持“lambda”的语言)中,您可以从函数返回一个函数,并且返回的函数将能够访问封闭的上下文,即使外部函数已经执行完毕。例如:

function counter(start){
    return function() {
        return start++;
    };
};

var f = counter(1);
alert( f() ); // now it's 1
alert( f() ); // now it's 2
alert( f() ); // now it's 3
var g = counter(10);
alert( g() ); // now it's 10
alert( g() ); // now it's 11
alert( f() ); // now it's 4!

3
虽然匿名函数默认情况下不是闭包,但 PHP 支持使用关键字 "use" 显式地创建闭包。更多信息请参见 http://blog.igstan.ro/2009/04/lambdas-and-closures-in-php-53.html。 - Flavius Stef
太酷了,我不知道那个。虽然语法有点丑陋,但很高兴看到PHP在赶上的过程中。 - mishoo
我可能在这里显露了我的无知……但是我认为lambda表达式是一个数学概念,与编程语言中的作用域无关(因此闭包!=lambda,尽管闭包解决方案通常包含lambda表达式的能力)……但像我说的,我可能漏掉了某些东西。 - MER

3
lambda函数有两个重要特点(至少是按照常用方式使用的):
  1. 它们可以被传递。一个函数可以将lambda函数作为参数或返回lambda函数。
  2. 它们可以访问它们定义的范围。因此,例如,lambda函数可以访问封闭函数的参数。
为了说明这对于基本示例的有用性,我将在Ruby中编写一个filter函数:
def filter(array, &lambda_function)
  new_array = []
  for item in array
    new_array.push(item) if lambda_function[item]
  end
  return new_array
end

$people_array = #imagine I have an array of Person objects here

def find_people_richer_than(threshold)
  return filter($people_array) {|person| person.wealth >= threshold}
end

我们的filter不知道我们将用什么标准进行过滤。这个逻辑都包含在我们传入的块(Ruby版本的lambda函数)中。但请注意,即使lambda函数实际上是在filter内部调用的,它仍然可以从定义它的地方知道阈值。


2
基本上,它是语法糖。你原本需要使用委托等10行代码才能完成的操作,现在可以用一行lambda表达式来实现。但是,在与其他开发人员一起工作时,要确保代码可读性仍然很好。
你可以内联附加事件 Button1_Click += (sender, eventArgs) => { //myCode }; 但是你将无法重用该事件,如果其中有很多代码,它也不能帮助保持代码的透明度。
你还可以创建一个lambda表达式从List<>中检索数据,但当有很多参数时,这可能变得相当不清晰,此时一个漂亮的LINQ查询会更加清晰。
这主要是个人选择,但我必须说我已经使用了很多次 :)
希望这能有所帮助, Sam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接