代码之家  ›  专栏  ›  技术社区  ›  sergtk

什么是lambda(函数)?

  •  654
  • sergtk  · 技术社区  · 17 年前

    对于一个没有计算机科学背景的人来说,计算机科学界的lambda是什么?

    22 回复  |  直到 7 年前
        1
  •  968
  •   Old Pro    7 年前

    lambda来自 Lambda Calculus 指编程中的匿名函数。

    为什么这么酷?它允许您在不命名的情况下编写快速丢弃函数。它还提供了一种编写闭包的好方法。有了这种能力,你就可以做这样的事情。

    蟒蛇

    def adder(x):
        return lambda y: x + y
    add5 = adder(5)
    add5(1)
    6
    

    从python的片段中可以看到,函数adder接受一个参数x,并返回一个匿名函数或lambda,它接受另一个参数y。该匿名函数允许您从函数创建函数。这是一个简单的例子,但它应该传递lambda和闭包所具有的强大功能。

    其他语言示例

    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
    

    C# 3.5 or higher

    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) 
    

    爪哇 看见 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,但它仍然有lambda。

    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
    
        2
  •  98
  •   Kevin Ji    14 年前

    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);
    }
    

    这调用计算器,不仅传递两个数字,而且调用计算器内部的哪个方法来获得计算结果。

    在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);
    }
    
        3
  •  60
  •   TylerH Ash Burlaczenko    8 年前

    它指的是 lambda calculus ,它是一个形式系统,只有lambda表达式,它表示一个函数,该函数接受一个函数作为其唯一参数并返回一个函数。lambda演算中的所有函数都是这种类型的,即, λ : λ → λ .

    Lisp使用lambda概念命名其匿名函数文本。此lambda表示一个函数,该函数接受两个参数x和y,并返回其乘积:

    (lambda (x y) (* x y)) 
    

    它可以像这样在线应用(计算为 五十 ):

    ((lambda (x y) (* x y)) 5 10)
    
        4
  •  53
  •   joel.neely    17 年前

    名称“lambda”只是一个历史产物。我们所说的是一个表达式,它的值是一个函数。

    一个简单的例子(将scala用于下一行)是:

    args.foreach(arg => println(arg))
    

    在哪里争论到 foreach 方法是匿名函数的表达式。上面这一行或多或少与编写类似的代码相同(不是很真实的代码,但您会明白这一点):

    void printThat(Object that) {
      println(that)
    }
    ...
    args.foreach(printThat)
    

    除此之外,您不必费心:

    1. 在其他地方声明函数(并在稍后重新访问代码时查找它)。
    2. 命名你只使用过一次的东西。

    一旦习惯了对值进行函数运算,没有这些值就好像被要求命名每个表达式一样愚蠢,比如:

    int tempVar = 2 * a + b
    ...
    println(tempVar)
    

    而不仅仅是在需要的地方编写表达式:

    println(2 * a + b)
    

    确切的符号因语言而异;并不总是需要希腊语!;-)

        5
  •  43
  •   isomorphismes Marcin    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):

    int square(int x)
    {
        return x * x;
    }
    

    变量x是一个形式参数,由实际 调用函数时要平方的值。在功能中 语言(方案)将定义相同的函数:

    (define square
      (lambda (x) 
        (* x x)))
    

    这在很多方面都不同,但它仍然使用形式参数 以同样的方式。


    补充: http://imgur.com/a/XBHub

    lambda

        6
  •  14
  •   Keith    17 年前

    稍微过于简单: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
    

    这与普通方法或匿名委托(实际上只是编译器的魔力)不同,因为它们不能 阅读 .

    并非所有使用lambda语法的c中的方法都可以编译为表达式树(即实际lambda函数)。例如:

    LinqToSqlContext.Where( 
        row => SomeComplexCheck( row.FieldName ) );
    

    现在无法读取表达式树-SomeComplexCheck无法分解。SQL语句将不使用WHERE执行,数据中的每一行都将通过 SomeComplexCheck .

    lambda函数不应与匿名方法混淆。例如:

    LinqToSqlContext.Where( 
        delegate ( DataRow row ) { 
            return row.FieldName > 15; 
        } );
    

    这也有一个“inline”函数,但这一次它只是编译器的魔力——C编译器将把它拆分成一个新的实例方法,并使用一个自动生成的名称。

    无法读取匿名方法,因此无法像对lambda函数那样转换逻辑。

        7
  •  7
  •   Jon Galloway    17 年前

    我喜欢这篇文章中对lambdas的解释: The Evolution Of LINQ And Its Impact On The Design Of C# . 这对我来说很有意义,因为它为兰姆达斯展示了一个真实的世界,并将其作为一个实际的例子加以构建。

    他们的快速解释:lambda是一种将代码(函数)视为数据的方法。

        8
  •  7
  •   CodingWithoutComments    17 年前

    Ruby中lambda的示例如下:

    hello = lambda do
        puts('Hello')
        puts('I am inside a proc')
    end
    
    hello.call
    

    将生成以下输出:

    Hello
    I am inside a proc
    
        9
  •  5
  •   Mark Cidade    17 年前

    @布莱恩,我一直在用C,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中的lambda也可以传递给报价运算符,然后作为列表列表进行遍历。一些强大的宏是这样生成的。

        10
  •  5
  •   Nick Louloudakis    9 年前

    这个问题得到了正式的回答,所以我不会再多加一点。

    非常简单, 非正式的 对于一个对数学或编程知之甚少或一无所知的人来说,我会把它解释为一个小的“机器”或“盒子”,它接受一些输入,做一些工作,产生一些输出,没有特定的名称,但我们知道它在哪里,仅凭这个知识,我们就使用它。

    实际上,对于一个知道函数是什么的人,我会告诉他们,它是一个没有名字的函数,通常放在内存中的一个点上,可以通过引用该内存来使用(通常通过变量的使用-如果他们听说过函数指针的概念,我会把它们作为类似的概念使用)。-这个答案涵盖了相当基础的内容(没有提到闭包等),但是我们可以很容易地理解这一点。

        11
  •  4
  •   mercutio    17 年前

    您可以将其视为一个匿名函数-以下是更多信息: Wikipedia - Anonymous Function

        12
  •  4
  •   Evg    7 年前

    只是因为我看不到这里的C++ 11例子,我会继续把这个好的例子从 here . 在搜索之后,它是我能找到的最清晰的语言特定的例子。

    你好,兰姆达斯,版本1

    template<typename F>
    
    void Eval( const F& f ) {
            f();
    }
    void foo() {
            Eval( []{ printf("Hello, Lambdas\n"); } );
    }
    

    你好,兰姆达斯,第2版:

    void bar() {
        auto f = []{ printf("Hello, Lambdas\n"); };
        f();
    }
    
        13
  •  3
  •   SarekOfVulcan    17 年前

    我很难用lambda表达式来表达自己的想法,因为我在VisualFoxPro中工作,它有宏替换和execscript和evaluate()函数,这些函数的作用似乎大致相同。

    ? Calculator(10, 23, "a + b")
    ? Calculator(10, 23, "a - b");
    
    FUNCTION Calculator(a, b, op)
    RETURN Evaluate(op)
    

    使用正式lambda的一个明显好处是(我假设)编译时检查:Fox在尝试运行文本字符串之前,不会知道您是否输入了上面的文本字符串。

    这对于数据驱动的代码也很有用:您可以将整个例程存储在数据库的备注字段中,然后在运行时对它们进行评估。这允许您调整应用程序的一部分,而实际上不需要访问源。(但这完全是另一个话题。)

        14
  •  3
  •   marc_s MisterSmith    8 年前

    对于一个没有计算机科学背景的人来说,计算机科学界的lambda是什么?

    我将用简单易读的python代码一步一步地直观地演示它。

    简而言之,lambda只是一个匿名的内联函数。

    让我们从任务开始了解 lambdas 作为一个有基础算术背景的大一学生。

    分配蓝图为“名称=值”,请参见:

    In [1]: x = 1
       ...: y = 'value'
    In [2]: x
    Out[2]: 1
    In [3]: y
    Out[3]: 'value'
    

    “x”、“y”是名称,“1”是值。 试一试数学中的函数

    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
    

    它现在起作用了,如果你坚持把两条分离线组合成一条呢? 来了 lambda

    In [13]: j = lambda i: i**2 + 2*i + 1
    In [14]: j
    Out[14]: <function __main__.<lambda>>
    

    未报告错误。

    这是一眼 兰姆达 它使您能够在一行中编写一个函数,就像在数学中一样,直接在计算机中编写函数。

    我们稍后再看。

    让我们继续深入研究“作业”。

    如上图所示,等号 = 适用于简单数据(1和“value”)类型和简单表达式(n**2+2*n+1)。

    试试这个:

    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
    

    它适用于简单的语句,在Python中有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 启用它工作

    In [23]: def m(n):
        ...:     if n > 0:
        ...:         return n**2 + 2*n + 1
        ...:
    In [24]: m(2)
    Out[24]: 9
    

    tada,分析它,“m”是名称,“n**2+2*n+1”是值。 : 是“=”的变体。
    找到它,如果只是为了理解,一切都从任务开始,一切都是任务。

    现在回到 兰姆达 ,我们有一个名为“m”的函数

    尝试:

    In [28]: m = m(3)
    In [29]: m
    Out[29]: 16
    

    这里有两个“m”的名字,函数 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
    

    它被称为“匿名函数”

    总之,

    1. 兰姆达 在一个内联函数中,它使您能够像在数学中一样以一条直线编写函数。
    2. 兰姆达 是匿名的

    希望,这有帮助。

        15
  •  2
  •   Serhat Ozgel    17 年前

    它是一个没有名称的函数。例如,在C中,您可以使用

    numberCollection.GetMatchingItems<int>(number => number > 5);
    

    返回大于5的数字。

    number => number > 5
    

    这里是lambda部分吗?它表示一个接受参数(数字)并返回布尔值(数字>5)的函数。GetMatchingItems方法对集合中的所有项使用此lambda,并返回匹配项。

        16
  •  2
  •   Michael come lately PhiLho    10 年前

    例如,在JavaScript中,函数被视为与其他所有函数相同的混合类型。( int , string , float , bool )因此,您可以在运行中创建函数,将它们分配给事物,并在以后调用它们。它很有用,但是,不是你想过度使用的东西,或者你会混淆所有在你之后必须维护你的代码的人…

    这是我正在玩的代码,看兔子洞有多深:

    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]()()();
    
        17
  •  1
  •   Ilian Zapryanov    13 年前

    我也明白了。我在JS上用过这个:

    var addAndMult = function(x) {
            return (function(y) {
                return (function(z) {
                    return (x+y)*z; 
                    });
                });
            };
    

    它增加2到4,然后将结果乘以6。但是我发现有时很难阅读:(

    我还做了一个有趣的foreach函数:

    var forEach = function(arr) {
                return (function(x) {
                for (var i=0; arr[i]; i++) {
                     x(arr[i]);
                 }
            });
        }
    

    foreach([1,2,3,4,5])(console.log);

    这个方法将迭代一个数组并执行一个操作——在这种情况下,打印到控制台。现在我也明白了为什么拉姆达是强大的。

        18
  •  1
  •   battlmonstr    9 年前

    在cs的上下文中,lambda函数是一个抽象的数学概念,它解决了数学表达式的符号评估问题。在这种情况下,lambda函数与 lambda term .

    但是在编程语言中,它是不同的。这是一段被宣布为“到位”的代码,可以作为“一流公民”传递。这个概念似乎很有用,因此它几乎可以应用到所有流行的现代编程语言中(参见 lambda functions everwhere 帖子)。

        19
  •  1
  •   konmik    9 年前

    在计算机编程中,lambda是一段代码(语句、表达式或它们的一组),它从外部源获取一些参数。它不能总是一个匿名函数——我们有很多方法来实现它们。

    我们在表达式、语句和函数之间有明确的分离,这是数学家没有的。

    编程中的“函数”一词也不同——我们有“函数是一系列要做的步骤”(从拉丁语“perform”)。在数学中,它是关于变量之间的相关性。

    函数语言试图尽可能地与数学公式相似,它们的单词含义几乎相同。但是在其他编程语言中,我们有不同的语言。

        20
  •  0
  •   madeinQuant    8 年前

    这个问题已经被完全回答了,我不想再详细讨论。我想分享一下在Rust中编写数值计算时的用法。

    有一个lambda(匿名函数)示例

    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 “。

    输出如下

    println!("f={:.6}      df={:.6}", f(10.0), df(10.0))
    
    f=98.000000       df=20.000000
    
        21
  •  0
  •   Martin Reiche    7 年前

    想象一下,你有一家有送货选择的餐厅,你有一份订单需要在30分钟内完成。关键是客户通常不在乎你是骑自行车送食物还是赤脚送食物,只要你保持食物的温暖和捆绑。因此,让我们将这个习语转换为具有匿名和定义的传输函数的javascript。

    下面我们定义了我们传递aka的方式,我们定义了一个函数的名称:

    // ES5 
    var food = function withBike(kebap, coke) {
    return (kebap + coke); 
    };
    

    如果我们使用arrow/lambda函数来完成这个传输,会怎么样?

    // ES6    
    const food = (kebap, coke) => { return kebap + coke };
    

    你看,对客户来说没有区别,也没有浪费时间去思考如何发送食物。就寄吧。

    顺便说一句,我不推荐带可乐的kebap,这就是为什么上面的代码会给你带来错误。玩得高兴。

        22
  •  0
  •   Andy Jazz    7 年前

    Lambda Function ,或者 Small Anonymous Function ,是一个独立的功能块,可以在代码中传递和使用。lambda在不同的编程语言中有不同的名称 Lambda 在里面 蟒蛇 科特林 , Closure 在里面 迅捷 Block 在里面 C Objtovi-C . 尽管lambda的意思在这些语言中非常相似,但有时它有一些细微的区别。

    让我们看看lambda(closure)如何在swift 4.2中使用sorted()方法从普通函数一直工作到最短表达式:

    let coffee: [String] = ["Cappuccino", "Espresso", "Latte", "Ristretto"]
    

    1。正规函数

    func backward(_ n1: String, _ n2: String) -> Bool {
        return n1 > n2
    }
    var reverseOrder = coffee.sorted(by: backward)
    
    
    // RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]
    

    2。闭包表达式

    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 } )
    

    4。从上下文推断类型

    reverseOrder = coffee.sorted(by: { n1, n2 in return n1 > n2 } )
    

    5。从单个表达式闭包隐式返回

    reverseOrder = coffee.sorted(by: { n1, n2 in n1 > n2 } )
    

    6。速记参数名称

    reverseOrder = coffee.sorted(by: { $0 > $1 } )
    
    // $0 and $1 are closure’s first and second String arguments.
    

    7。操作员方法

    reverseOrder = coffee.sorted(by: >)
    
    // RESULT: ["Ristretto", "Latte", "Espresso", "Cappuccino"]
    

    希望这有帮助。

    推荐文章