对于没有comp-sci背景的人来说,计算机科学领域的lambda是什么?
Lambda来自Lambda微积分,指的是编程中的匿名函数.
为什么这很酷?它允许您在不命名的情况下编写快速丢弃功能.它还提供了一种编写闭包的好方法.有了这种力量,你就可以做到这样的事情.
蟒蛇
def adder(x):
return lambda y: x + y
add5 = adder(5)
add5(1)
6
正如您从Python的片段中看到的那样,函数加法器接受参数x,并返回一个匿名函数或lambda,它接受另一个参数y.该匿名函数允许您从函数创建函数.这是一个简单的例子,但它应该传达lambda和闭包的力量.
其他语言的例子
JavaScript的
sub adder {
my ($x) = @_;
return sub {
my ($y) = @_;
$x + $y
}
}
my $add5 = adder(5);
print &$add5(1) == 6 ? "ok\n" : "not ok\n";
JavaScript(ES6)
var adder = function (x) {
return function (y) {
return x + y;
};
};
add5 = adder(5);
add5(1) == 6
方案
const adder = x => y => x + y;
add5 = adder(5);
add5(1) == 6
C#3.5或更高
(define adder
(lambda (x)
(lambda (y)
(+ x y))))
(define add5
(adder 5))
(add5 1)
6
迅速
Func> adder =
(int x) => (int y) => x + y; // `int` declarations optional
Func add5 = adder(5);
var add6 = adder(6); // Using implicit typing
Debug.Assert(add5(1) == 6);
Debug.Assert(add6(-1) == 5);
// Closure example
int yEnclosed = 1;
Func addWithClosure =
(x) => x + yEnclosed;
Debug.Assert(addWithClosure(2) == 3);
PHP
func adder(x: Int) -> (Int) -> Int{
return { y in x + y }
}
let add5 = adder(5)
add5(1)
6
哈斯克尔
$a = 1;
$b = 2;
$lambda = function () use (&$a, &$b) {
echo $a + $b;
};
echo $lambda();
Java看到这篇文章
(\x y -> x + y)
LUA
// The following is an example of Predicate :
// a functional interface that takes an argument
// and returns a boolean primitive type.
Predicate pred = x -> x % 2 == 0; // Tests if the parameter is even.
boolean result = pred.test(4); // true
科特林
adder = function(x)
return function(y)
return x + y
end
end
add5 = adder(5)
add5(1) == 6 -- true
红宝石
Ruby略有不同,因为你不能使用与调用函数完全相同的语法来调用lambda,但它仍然有lambdas.
val pred = { x: Int -> x % 2 == 0 }
val result = pred(4) // true
Ruby是Ruby,有一个lambdas的简写,所以你可以这样定义adder
:
def adder(x)
lambda { |y| x + y }
end
add5 = adder(5)
add5[1] == 6
lambda是一种函数,内联定义.除了lambda之外,你通常还有一些变量类型可以保存对函数,lambda或其他函数的引用.
例如,这是一段不使用lambda的C#代码:
public Int32 Add(Int32 a, Int32 b)
{
return a + b;
}
public Int32 Sub(Int32 a, Int32 b)
{
return a - b;
}
public delegate Int32 Op(Int32 a, Int32 b);
public void Calculator(Int32 a, Int32 b, Op op)
{
Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}
public void Test()
{
Calculator(10, 23, Add);
Calculator(10, 23, Sub);
}
这会调用Calculator,不仅传递两个数字,而且调用Calculator内部的方法来获取计算结果.
在C#2.0中,我们获得了匿名方法,将上述代码缩短为:
public delegate Int32 Op(Int32 a, Int32 b);
public void Calculator(Int32 a, Int32 b, Op op)
{
Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}
public void Test()
{
Calculator(10, 23, delegate(Int32 a, Int32 b)
{
return a + b;
});
Calculator(10, 23, delegate(Int32 a, Int32 b)
{
return a - b;
});
}
然后在C#3.0中我们得到了lambda,它使代码更短:
public delegate Int32 Op(Int32 a, Int32 b);
public void Calculator(Int32 a, Int32 b, Op op)
{
Console.WriteLine("Calculator: op(" + a + ", " + b + ") = " + op(a, b));
}
public void Test()
{
Calculator(10, 23, (a, b) => a + b);
Calculator(10, 23, (a, b) => a - b);
}
"lambda"这个名字只是一个历史文物.我们所谈论的只是一个表达式,其值是一个函数.
一个简单的例子(使用Scala作为下一行)是:
args.foreach(arg => println(arg))
其中foreach
方法的参数是匿名函数的表达式.上面这行与写这样的东西大致相同(不是真正的代码,但你会得到这个想法):
void printThat(Object that) { println(that) } ... args.foreach(printThat)
除了你不需要打扰:
在其他地方声明该函数(并在以后重新访问代码时必须查找它).
命名您只使用一次的东西.
一旦习惯了函数值,不必使用它们就像要求命名每个表达式一样愚蠢,例如:
int tempVar = 2 * a + b ... println(tempVar)
而不是只在你需要的地方写表达式:
println(2 * a + b)
确切的表示法因语言而异; 希腊语并不总是必需的!;-)
它指的是lambda演算,它是一个只有lambda表达式的正式系统,它表示一个函数,它为其唯一的参数获取一个函数并返回一个函数.lambda演算中的所有函数都属于那种类型,即? : ? ? ?
.
Lisp使用lambda概念来命名它的匿名函数文字.这个lambda代表一个函数,它接受两个参数x和y,并返回它们的产品:
(lambda (x y) (* x y))
它可以像这样在线应用(评估为50):
((lambda (x y) (* x y)) 5 10)
lambda演算是一种一致的数学替代理论.在学校数学中,人们看到例如x+y=5
配对x?y=1
.除了操纵单个方程的方法之外,还可以将来自这两个方程的信息放在一起,只要逻辑上完成交叉方程替换.Lambda演算法编写了进行这些替换的正确方法.
鉴于y = x?1
是第二个方程的有效重排,这样的:? y = x?1
意味着替换符号的函数x?1
的符号y
.现在想象一下应用于? y
第一个等式中的每个项.如果一个术语y
然后执行替换; 否则什么也不做.如果你在纸上执行此操作,你会看到如何应用这? y
将使第一个等式可以解决.
没有任何计算机科学或编程,这是一个答案.
我能想到的最简单的编程示例来自http://en.wikipedia.org/wiki/Joy_(programming_language)#How_it_works:
这里是如何在命令式编程语言(C)中定义square函数:
int square(int x) { return x * x; }变量x是形式参数,在调用函数时由实际值替换为平方.在函数式语言(Scheme)中,将定义相同的函数:
(define square (lambda (x) (* x x)))这在许多方面是不同的,但它仍然以相同的方式使用形式参数x.
补充: http ://imgur.com/a/XBHub
略微过度简化:lambda函数是一个可以传递给其他函数并且可以访问逻辑的函数.
在C#中,lambda语法通常以与匿名委托相同的方式编译为简单方法,但它也可以被分解并读取其逻辑.
例如(在C#3中):
LinqToSqlContext.Where( row => row.FieldName > 15 );
LinqToSql可以读取该函数(x> 15)并将其转换为实际的SQL以使用表达式树执行.
上述声明变为:
select ... from [tablename] where [FieldName] > 15 --this line was 'read' from the lambda function
这与普通方法或匿名委托(实际上只是编译器魔法)不同,因为它们无法读取.
并非C#中使用lambda语法的所有方法都可以编译为表达式树(即实际的lambda函数).例如:
LinqToSqlContext.Where( row => SomeComplexCheck( row.FieldName ) );
现在无法读取表达式树 - SomeComplexCheck无法分解.SQL语句将在没有where的情况下执行,并且数据中的每一行都将被接通SomeComplexCheck
.
Lambda函数不应与匿名方法混淆.例如:
LinqToSqlContext.Where( delegate ( DataRow row ) { return row.FieldName > 15; } );
这也有一个'内联'函数,但这次它只是编译器魔术 - C#编译器会将其拆分为具有自动生成名称的新实例方法.
匿名方法无法读取,因此逻辑无法转换为lambda函数.
我喜欢本文中对Lambdas的解释:LINQ的演变及其对C#设计的影响.它对我来说很有意义,因为它展示了Lambdas的真实世界,并将其作为一个实际例子构建出来.
他们的快速解释:Lambdas是一种将代码(函数)视为数据的方法.
Ruby中lambda的一个例子如下:
hello = lambda do puts('Hello') puts('I am inside a proc') end hello.call
将生成以下输出:
Hello I am inside a proc
@Brian我一直在C#中使用lambdas,在LINQ和非LINQ运算符中.例:
string[] GetCustomerNames(IEnumerablecustomers) { return customers.Select(c=>c.Name); }
在C#之前,我使用JavaScript中的匿名函数来回调AJAX函数,之后创建了Ajax这个术语:
getXmlFromServer(function(result) {/*success*/}, function(error){/*fail*/});
然而,C#的lambda语法的有趣之处在于它们自己的类型不能被推测(即,你不能输入var foo =(x,y)=> x*y)但是它们取决于它们的类型分配给它们,它们将被编译为表示表达式的委托或抽象语法树(这是LINQ对象映射器如何进行"语言集成"魔术).
LISP中的Lambdas也可以传递给报价运算符,然后作为列表列表遍历.一些强大的宏是以这种方式制作的.
这个问题正式得到了很好的回答,所以我不会试图在此上添加更多内容.
对于那些对数学或编程知之甚少或根本不知道的人来说,非常简单,非正式的话,我会把它解释为一个小的"机器"或"盒子",需要一些输入,做一些工作并产生一些输出,没有特别的名字,但我们知道它在哪里,只有这些知识,我们才能使用它.
实际上,对于一个知道函数是什么的人,我会告诉他们这是一个没有名字的函数,通常放在内存中只能通过引用该内存来使用(通常是通过使用一个变量 - 如果他们已经听说过函数指针的概念,我会将它们用作类似的概念) - 这个答案涵盖了漂亮的基础知识(没有提到闭包等),但是人们可以很容易地理解它.