对于没有comp-sci背景的人来说,计算机科学领域的lambda是什么?
Lambda来自Lambda Calculus,指的是编程中的匿名函数。
为什么这很酷?它允许您在不命名的情况下编写快速丢弃功能。它还提供了一种编写闭包的好方法。有了这种力量,你就可以做到这样的事情。
蟒蛇
def adder(x):
return lambda y: x + y
add5 = adder(5)
add5(1)
6
正如您从Python的片段中看到的那样,函数加法器接受参数x,并返回一个匿名函数或lambda,它接受另一个参数y。该匿名函数允许您从函数创建函数。这是一个简单的例子,但它应该传达lambda和闭包的力量。
其他语言的例子
Perl 5
sub adder {
my ($x) = @_;
return sub {
my ($y) = @_;
$x + $y
}
}
my $add5 = adder(5);
print &$add5(1) == 6 ? "ok\n" : "not ok\n";
JavaScript的
var adder = function (x) {
return function (y) {
return x + y;
};
};
add5 = adder(5);
add5(1) == 6
JavaScript(ES6)
const adder = x => y => x + y;
add5 = adder(5);
add5(1) == 6
方案
(define adder
(lambda (x)
(lambda (y)
(+ x y))))
(define add5
(adder 5))
(add5 1)
6
Func<int, Func<int, int>> adder =
(int x) => (int y) => x + y; // `int` declarations optional
Func<int, int> 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<int, int> addWithClosure =
(x) => x + yEnclosed;
Debug.Assert(addWithClosure(2) == 3);
迅速
func adder(x: Int) -> (Int) -> Int{
return { y in x + y }
}
let add5 = adder(5)
add5(1)
6
PHP
$a = 1;
$b = 2;
$lambda = function () use (&$a, &$b) {
echo $a + $b;
};
echo $lambda();
哈斯克尔
(\x y -> x + y)
Java见this post
// The following is an example of Predicate :
// a functional interface that takes an argument
// and returns a boolean primitive type.
Predicate<Integer> 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
科特林
val pred = { x: Int -> x % 2 == 0 }
val result = pred(4) // true
红宝石
Ruby略有不同,因为你不能使用与调用函数完全相同的语法来调用lambda,但它仍然有lambdas。
def adder(x)
lambda { |y| x + y }
end
add5 = adder(5)
add5[1] == 6
Ruby是Ruby,有一个lambdas的简写,所以你可以这样定义adder
:
def adder(x)
-> y { x + y }
end
这个问题正式得到了很好的回答,所以我不会试图在此上添加更多内容。
对于那些对数学或编程知之甚少或根本不知道的人来说,非常简单,非正式的话,我会把它解释为一个小的“机器”或“盒子”,需要一些输入,做一些工作并产生一些输出,没有特别的名字,但我们知道它在哪里,只有这些知识,我们才能使用它。
实际上,对于一个知道函数是什么的人,我会告诉他们这是一个没有名字的函数,通常放在内存中只能通过引用该内存来使用(通常是通过使用一个变量 - 如果他们已经听说过函数指针的概念,我会将它们用作类似的概念) - 这个答案涵盖了漂亮的基础知识(没有提到闭包等),但是人们可以很容易地理解它。
您可以将其视为匿名函数 - 这里有更多信息:Wikipedia - Anonymous Function
仅仅因为我在这里看不到C ++ 11的例子,我将继续发布这个来自here的好例子。搜索之后,这是我能找到的最清晰的语言特定示例。
template<typename F>
void Eval( const F& f ) {
f();
}
void foo() {
Eval( []{ printf("Hello, Lambdas\n"); } );
}
void bar() {
auto f = []{ printf("Hello, Lambdas\n"); };
f();
}
我无法在lambda表达式中包围我的头,因为我在Visual FoxPro中工作,它具有宏替换以及ExecScript {}和Evaluate()函数,它们似乎具有相同的用途。
? Calculator(10, 23, "a + b")
? Calculator(10, 23, "a - b");
FUNCTION Calculator(a, b, op)
RETURN Evaluate(op)
使用正式lambdas的一个明显的好处是(我假设)编译时检查:Fox不会知道你是否在上面的文本字符串上输入错误,直到它试图运行它。
这对于数据驱动的代码也很有用:您可以将整个例程存储在数据库的备注字段中,然后在运行时对它们进行评估。这使您可以调整部分应用程序,而无需实际访问源。 (但这完全是另一个话题。)
对于没有comp-sci背景的人来说,计算机科学领域的lambda是什么?
我将在简单易读的python代码中逐步直观地说明它。
简而言之,lambda只是一个匿名和内联函数。
让我们从任务开始,将lambdas
理解为具有基本算术背景的新生。
赋值蓝图是'name = value',请参阅:
In [1]: x = 1
...: y = 'value'
In [2]: x
Out[2]: 1
In [3]: y
Out[3]: 'value'
'x','y'是名称和1,'value'是值。尝试数学函数
In [4]: m = n**2 + 2*n + 1
NameError: name 'n' is not defined
错误报告, 你不能直接把数学写成代码,应该定义'n'或者赋值给它。
In [8]: n = 3.14
In [9]: m = n**2 + 2*n + 1
In [10]: m
Out[10]: 17.1396
它现在有效,如果你坚持将两个单独的线组合成一个,那该怎么办呢。来自qazxsw poi
lambda
没有错误报告。
这是对In [13]: j = lambda i: i**2 + 2*i + 1
In [14]: j
Out[14]: <function __main__.<lambda>>
的一瞥,它使您能够像在数学中一样直接在计算机中编写函数。
我们稍后会看到它。
让我们继续深入挖掘“任务”。
如上所示,等号符号lambda
适用于简单数据(1和'值')类型和简单表达式(n ** 2 + 2 * n + 1)。
试试这个:
=
它适用于简单的语句,在python In [15]: x = print('This is a x')
This is a x
In [16]: x
In [17]: x = input('Enter a x: ')
Enter a x: x
中有11种类型
复合语句怎么样,
7. Simple statements — Python 3.6.3 documentation
有In [18]: m = n**2 + 2*n + 1 if n > 0
SyntaxError: invalid syntax
#or
In [19]: m = n**2 + 2*n + 1, if n > 0
SyntaxError: invalid syntax
使它工作
def
Tada,分析它,'m'是名字,'n ** 2 + 2 * n + 1'是value.In [23]: def m(n):
...: if n > 0:
...: return n**2 + 2*n + 1
...:
In [24]: m(2)
Out[24]: 9
是'='的变体。
找到它,如果只是为了理解,一切都从作业开始,一切都是作业。
现在回到:
,我们有一个名为'm'的函数
尝试:
lambda
这里有两个名字'm',函数In [28]: m = m(3)
In [29]: m
Out[29]: 16
已经有一个名字,重复。
它的格式如下:
m
这不是一个聪明的策略,所以错误报告
我们必须删除其中一个,设置一个没有名称的函数。
In [27]: m = def m(n):
...: if n > 0:
...: return n**2 + 2*n + 1
SyntaxError: invalid syntax
它被称为'匿名功能'
结论,
m = lambda n:n**2 + 2*n + 1
在内联函数中,使您能够像在数学中一样在一条直线上编写函数lambda
是匿名的希望这可以帮助。
这是一个没有名字的功能。对于例如在c#中你可以使用
lambda
返回大于5的数字。
numberCollection.GetMatchingItems<int>(number => number > 5);
是这里的lambda部分。它表示一个函数,它接受一个参数(数字)并返回一个布尔值(数字> 5)。 GetMatchingItems方法在集合中的所有项目上使用此lambda并返回匹配的项目。
例如,在Javascript中,函数被视为与其他所有函数相同的混合类型(number => number > 5
,int
,string
,float
)。因此,您可以动态创建函数,将它们分配给事物,稍后再调用它们。这很有用但是,不是你想要过度使用的东西,或者你会混淆每个必须维护你的代码的人...
这是我正在玩的一些代码,看看这个兔子洞有多深:
bool
在CS的上下文中,lambda函数是一个抽象的数学概念,它解决了数学表达式的符号评估问题。在该上下文中,lambda函数与var x = new Object;
x.thingy = new Array();
x.thingy[0] = function(){ return function(){ return function(){ alert('index 0 pressed'); }; }; }
x.thingy[1] = function(){ return function(){ return function(){ alert('index 1 pressed'); }; }; }
x.thingy[2] = function(){ return function(){ return function(){ alert('index 2 pressed'); }; }; }
for(var i=0 ;i<3; i++)
x.thingy[i]()()();
相同。
但在编程语言中,它有所不同。这是一段被宣布为“就地”的代码,可以作为“一等公民”传播。这个概念似乎很有用,因此几乎所有流行的现代编程语言都有用(参见lambda term帖子)。
我也懂了我在JS中试过这个:
lambda functions everwhere
它增加2到4然后暗示结果为6.但是我发现它有时难以阅读:(
我也为每个函数做了一个有趣的事情:
var addAndMult = function(x) {
return (function(y) {
return (function(z) {
return (x+y)*z;
});
});
};
的forEach([1,2,3,4,5])(的console.log);
此方法将迭代数组并执行操作 - 在打印到控制台的情况下。现在我也明白为什么labmdas是强大的。
在计算机编程中,lambda是一段代码(语句,表达式或它们的一组),它从外部源获取一些参数。它不一定总是一个匿名函数 - 我们有很多方法来实现它们。
我们在表达式,陈述和函数之间有明确的分离,这是数学家没有的。
编程中的“功能”一词也有所不同 - 我们有“功能是一系列要做的步骤”(来自拉丁语“perform”)。在数学中,它是变量之间的相关性。
功能语言试图尽可能与数学公式相似,它们的意思几乎相同。但在其他编程语言中,我们有不同之处。
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);
}
var forEach = function(arr) { return (function(x) { for (var i=0; arr[i]; i++) { x(arr[i]); } }); }
或Lambda Function
是一个独立的功能块,可以在代码中传递和使用。 Lambda在不同的编程语言中有不同的名称 - Python和Kotlin中的Small Anonymous Function
,Swift中的Lambda
,或C和Objective-C中的Closure
。尽管lambda的含义与这些语言非常相似,但它有时会略有区别。
Block
let coffee: [String] = ["Cappuccino", "Espresso", "Latte", "Ristretto"]
func backward(_ n1: String, _ n2: String) -> Bool {
return n1 > n2
}
var reverseOrder = coffee.sorted(by: backward)
// RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]
reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool in
return n1 > n2
})
reverseOrder = coffee.sorted(by: { (n1: String, n2: String) -> Bool in return n1 > n2 } )
reverseOrder = coffee.sorted(by: { n1, n2 in return n1 > n2 } )
reverseOrder = coffee.sorted(by: { n1, n2 in n1 > n2 } )
reverseOrder = coffee.sorted(by: { $0 > $1 } )
// $0 and $1 are closure’s first and second String arguments.
希望这可以帮助。
这个问题已经得到了充分的回答,我不想详细介绍。我想在生锈中编写数值计算时分享用法。
有一个lambda(匿名函数)的例子
reverseOrder = coffee.sorted(by: >)
// RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]
当我编写Newton-Raphson方法的模块时,它被用作一阶和二阶导数。 (如果你想知道什么是Newton-Raphson方法,请访问“let f = |x: f32| -> f32 { x * x - 2.0 };
let df = |x: f32| -> f32 { 2.0 * x };
”。
输出如下
https://en.wikipedia.org/wiki/Newton%27s_method
想象一下,您有一个带有送货选项的餐厅,您需要在30分钟内完成订单。关键是客户通常不在乎你是否用汽车或赤脚骑自行车送食物,只要你保持餐后温暖和捆绑。因此,让我们使用匿名和定义的传输函数将此习语转换为Javascript。
下面我们定义了我们的交付方式,我们定义了一个函数的名称:
println!("f={:.6} df={:.6}", f(10.0), df(10.0))
f=98.000000 df=20.000000
如果我们使用箭头/ lambda函数来完成这个转移怎么办:
// ES5
var food = function withBike(kebap, coke) {
return (kebap + coke);
};
你看到客户没有区别,没有时间浪费思考如何送食物。只需发送它。
顺便说一句,我不推荐使用可乐的kebap这就是为什么上面的代码会给你错误。玩得开心。
它指的是lambda calculus,它是一个只有lambda表达式的正式系统,它表示一个函数,它为其唯一的参数获取一个函数并返回一个函数。 lambda演算中的所有函数都属于那种类型,即λ : λ → λ
。
Lisp使用lambda概念来命名它的匿名函数文字。这个lambda代表一个函数,它接受两个参数x和y,并返回它们的产品:
(lambda (x y) (* x y))
它可以像这样在线应用(评估为50):
((lambda (x y) (* x y)) 5 10)
“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演算是一种一致的数学替代理论。在学校数学中,人们看到例如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):
int square(int x) { return x * x; }
变量x是形式参数,在调用函数时由实际值替换为平方。在函数式语言(Scheme)中,将定义相同的函数:
(define square (lambda (x) (* x x)))
这在许多方面是不同的,但它仍然以相同的方式使用形式参数x。
略微过度简化: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的解释:The Evolution Of LINQ And Its Impact On The Design Of 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(IEnumerable<Customer> customers)
{ 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也可以传递给报价运算符,然后作为列表列表遍历。一些强大的宏是以这种方式制作的。