函数和lambda有什么区别?


54

我对“功能”和“ lambda”有些困惑。我看过一些例子,它们表明scheme关键字的lambda工作方式与JavaScript关键字非常相似function,但是我真的不知道它们之间的关系。

有人告诉我说.net中的对象时,“功能”和“方法”可以互换使用。我想知道“ lambda”和“ function”是否同样含义相同。看到希腊字母lambda(λ)出现在此站点上的许多化身中,我不知道'lambda'是否具有某些深奥的含义。更让人困惑的是,在.net中,C#的功能部分将传递给另一个函数的函数表达式称为“ lambda表达式”,因此,这个词似乎无处不在。

我对“ lambda演算”一词也很熟悉。

函数和lambda有什么区别?


3
Nitpick-至少在C#/。NET文档中,它们被称为“ lambda表达式”,而不是“ lambda函数”。
Oded 2012年

@ TWith2Sugars-阅读消息。您的回答质量低下,因为它几乎只是一个链接,因此被转换为评论。
Oded 2012年

17
I wonder if 'lambda' has some esoteric meaning, seeing that the Greek letter lambda (λ) appears in so many avatars on this site.有人希望可以参考lambda演算,但我有一种奇怪的感觉,那就是应将半条命归咎于lambda化身。
yannis 2012年

3
足够公平,这是stackoverflow答案的链接: stackoverflow.com/questions/16501/what-is-a-lambda-function
TWith2Sugars 2012年

@ZaphodBeeblebrox:我怀疑您对《半条命》的影响是正确的。:/
FrustratedWithFormsDesigner 2012年

Answers:


44

单词“ lambda”或“ lambda表达式”通常是指匿名函数。因此,从某种意义上讲,lambda是一种函数,但并非每个函数都是lambda(即,命名的函数通常不称为lambda)。根据语言的不同,匿名函数的实现方式通常与命名函数不同(特别是在匿名函数是闭包而命名函数不是闭包的语言中),因此用不同的术语来引用它们是有意义的。

scheme的lambda关键字和Javascript的function关键字之间的区别在于,后者可用于创建匿名函数和命名函数,而前者仅可创建匿名函数(并且您将用于define创建命名函数)。

λ演算是一种最小的编程语言/数学计算模型,它使用函数作为其唯一的“数据结构”。在lamdba演算中,lambda符号用于创建(匿名)函数。这是其他语言中术语“ lambda”的使用来源。


1
那是非常粗糙的。您使用define(或let它的一个亲戚,或一个内部定义)创建名称-仅此而已。在define功能方面没有什么特别的。
Eli Barzilay 2012年

2
@EliBarzilay好吧,define 确实有一种定义函数的特殊形式(例如,您可以编写(define (f x) (foo))而不是(define f (lambda (x) (foo)))),但是我的观点是,您不能lambda单独使用一个命名函数,即,您不能编写类似于(lambda f (x) (foo))定义命名函数的内容f它需要一个参数,就像使用Javascript的function关键字一样。
sepp2k 2012年

1
define具有作为语法糖的功能,因此它不如其作为所有值的名称绑定工具的角色那么重要。至于lambda不自己创建名称:这是一个重要功能,因为它可以将名称给出与功能形式分开... IMO JS在允许分隔的同时做对了正确的事情,同时也为那些可能惊恐的群众接受可选名称没有名称的函数的想法。(而且幸运的是,这些群众的规模总体呈下降趋势……)
Eli Barzilay 2012年

18

Lambda只是一个匿名函数-一个没有名称的函数。


4
注意事项:lambda可以包含它们在声明它们的上下文中存在的状态(如在闭包中一样)。
马丁·约克

7
如果语言允许您声明嵌套函数,那么命名函数也可以。
cHao 2012年

4
将其加入“低质量的帖子”评论标签,并带有较高的答案,这是一种荣誉。
尼斯,2012年

@ZaphodBeeblebrox-不是故意的,我可以向你保证。
奥德

并非如此,lambdaScheme中的function表达式就像没有名称的表达式一样,但是没有什么可以阻止您以后给它们命名。例如var f = [function(x){return x;}][0]。您可能会争辩说函数值本身没有名称,但是所有函数都适用……
Eli Barzilay 2012年


8

在C#中,匿名函数是一个通用术语,包括lambda表达式和匿名方法(匿名方法是没有实际方法声明的委托实例)。

Lambda表达式可以分解为表达式Lambda语句Lambda

表达式lambda:

(int x, string y) => x == y.Length 

语句lambda与表达式lambda相似,除了语句用大括号括起来:

(int x, string y) => {
         if (x == y.Length) {
             Console.WriteLine(y);
         }
}

当我们谈论JavaScript中的lambda表达式时,基本上只是意味着在调用另一个函数时将一个函数用作参数。

var calculate = function(x, y, operation){
    return operation(x, y);
}

// we're passing anonymous function as a third argument
calculate(10, 15, function(x, y) {
    return x + y;
}); // 25

+1很多人都提到过lambda是匿名函数,但除此之外,还有更多。Lambda的主体(右手侧)通常是表达式而不是语句块。命名函数的主体(即表达式)通常在功能语言中(而不是在命令性语言中)允许(或要求)。
Zantier

4

TL; DR正如其他人指出的那样:lambda表示法只是一种定义函数的方法,而不必强迫给它们命名。

长版

我想对此主题进行详细说明,因为我觉得它很有趣。免责声明:我很早以前就学习过lambda演算课程。如果知识更好的人发现我的答案有任何不正确之处,请随时帮助我进行改进。

让我们从表达式开始,例如1 + 2x + 2。诸如1和的文字2称为常量,因为它们绑定到特定的固定值。

诸如变量之类的标识符x称为变量,为了对其进行评估,您需要首先将其绑定到某个值。因此,基本上x + 1,只要您不知道是什么,就无法进行评估x

lambda表示法提供了用于将特定输入值绑定到变量的架构。甲lambda表达式可以通过添加可形成λx .在现有表达的前面,例如λx . x + 1。变量x被认为是自由x + 1必然λx . x + 1

这对评估表达式有何帮助?如果您向lambda表达式输入值,就像这样

(λx . x + 1) 2

那么您可以通过用x值2 替换(绑定)所有出现的变量来评估整个表达式:

(λx . x + 1) 2
      2 + 1
      3

因此,lambda表示法提供了一种将事物绑定到出现在表达式/程序块中的变量的通用机制。根据上下文,这会在编程语言中创建明显不同的概念:

  • 在像Haskell这样的纯函数式语言中,lambda表达式表示数学意义上的函数:将输入值注入到lambda的主体中,并产生输出值。
  • 在许多语言(例如JavaScript,Python,Scheme)中,评估Lambda表达式的主体可能会产生副作用。在这种情况下,可以使用术语过程来标记纯功能的差异。

除了差异之外,lambda表示法是关于定义形式参数并将其绑定到实际参数。

下一步,就是给函数/过程起个名字。在几种语言中,函数都是与其他函数一样的值,因此可以给函数命名,如下所示:

(define f (lambda (x) (+ x 1)))      ;; Scheme

f = \x -> x + 1                      -- Haskell

val f: (Int => Int) = x => x + 1     // Scala

var f = function(x) { return x + 1 } // JavaScript

f = lambda x: x + 1                  # Python

正如Eli Barzilay指出的那样,这些定义只是将名称绑定f到一个值,而该值恰好是一个函数。因此,就此而言,函数,数字,字符串,字符都是可以以相同方式绑定到名称的值:

(define n 42)   ;; Scheme

n = 42          -- Haskell

val n: Int = 42 // Scala

var n = 42      // JavaScript

n = 42          # Python

在这些语言中,您还可以使用更熟悉(但等效)的符号将函数绑定到名称:

(define (f x) (+ x 1))         ;; Scheme

f x = x + 1                    -- Haskell

def f(x: Int): Int = x + 1     // Scala

function f(x) { return x + 1 } // JavaScript

def f(x): return x + 1         # Python

某些语言(例如C)仅支持后者的符号来定义(命名)函数。

关闭

关于闭包的最终结论。考虑一下表达式x + y。它包含两个自由变量。如果x使用lambda表示法进行绑定,则会得到:

\x -> x + y

这还不是一个函数,因为它仍然包含一个free变量y。您也可以通过绑定来实现一个功能y

\x -> \y -> x + y

要么

\x y -> x + y

+功能相同。

但是您可以y用另一种方式(*)进行绑定:

incrementBy y = \x -> x + y

将函数increasingBy应用于数字的结果是闭包,即函数/过程,其主体包含一个自由变量(例如y),该变量已绑定到定义了闭包的环境中的值。

因此,incrementBy 5是由5递增的数字功能(关闭)。

注意 (*)

我在这里有点作弊:

incrementBy y = \x -> x + y

相当于

incrementBy = \y -> \x -> x + y

因此绑定机制是相同的。直观地,我认为闭包代表了更复杂的lambda表达式的一部分。创建此表示形式时,已经设置了母表达式的某些绑定,并且闭包在稍后对其求值/调用时会使用它们。


我只是一个初学者,但是如果您尝试从数学意义上理解λ微积分,我认为这可能会有点令人困惑,因为您所谓的常数称为变量,并由符号a,b,c表示。调用变量将是不确定的变量 x。在另一方面1是λ ˚F X˚F X,2是λ ˚F Xff x)等等。
jinawee

@jinawee:我承认我没有查找确切的定义。我记得在逻辑中使用术语变量和常量。在那里,常量是映射到域的符号,而变量是可以量化的符号。但是,同样,(1)自从我学习逻辑课程以来已经很久了,(2)λ演算不必遵循1-1的数学逻辑概念。如果您为我提供参考,我可以尝试修复我的术语。
乔治

0

编程中的“ Lambda”通常表示“ lambda函数”(或“ lambda表达式”,“ lambda术语”)。当函数是在用法之前定义的命名代码块时,“ lambda函数”是代替用法而定义的代码块(或表达式),可以在编程语言中用作一等公民。

在JavaScript ES6(2015)中,有一种简短的语法定义了lambda,称为“ Arrow Functions”。在C#中,.NET 3.0(大约在2006年)引入了这种语法。

在数学中,“函数”概念具有多种含义,其中一种含义是关于函数的表示法(即如何将其写下来),然后“ lambda函数”(在微积分中)是一种特殊的函数表示法。有关更多讨论,请检查编程语言中的lambda函数

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.