首页 文章

什么是lambda(函数)?

提问于
浏览
642

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

21 回答

  • 6

    例如,在Javascript中,函数被视为与其他所有函数相同的混合类型( intstringfloatbool ) . 因此,您可以动态创建函数,将它们分配给事物,稍后再调用它们 . 它会让所有在你之后维护代码的人感到困惑......

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

    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]()()();
    
  • 1

    略微过度简化: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函数 .

  • 2

    在CS的上下文中,lambda函数是一个抽象的数学概念,它解决了数学表达式的符号评估问题 . 在该上下文中,lambda函数与lambda term相同 .

    但是在编程语言中,'s something different. It'是一段声明为"in place"的代码,并且可以作为"first-class citizen"传递 . 这个概念似乎很有用,因此它几乎可以用于所有流行的现代编程语言(见lambda functions everwhere post) .

  • 3

    Ruby中lambda的一个例子如下:

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

    将生成以下输出:

    Hello
    I am inside a proc
    
  • 4

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

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

  • 3

    这是一个没有名字的功能 . 对于例如在c#中你可以使用

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

    返回大于5的数字 .

    number => number > 5
    

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

  • 1

    这个问题得到了正式的回答,所以我不会试图在此上添加更多内容 .

    对于那些对数学或编程知之甚少或者一无所知的人来说非常简单,我会把它解释为一个小的"machine"或"box",需要一些输入,做一些工作并产生一些输出,没有特别的名字,但我们知道只有这些知识才能使用它 .

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

  • 2

    它指的是lambda calculus,它是一个只有lambda表达式的正式系统,它表示一个函数,它为其唯一的参数获取一个函数并返回一个函数 . lambda演算中的所有函数都属于该类型,即 λ : λ → λ .

    Lisp使用lambda概念来命名它的匿名函数文字 . 这个lambda代表一个函数,它接受两个参数x和y,并返回它们产品:

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

    它可以像这样在线应用(评估为50):

    ((lambda (x y) (* x y)) 5 10)
    
  • 949

    您可以将其视为匿名函数 - 这里有更多信息:Wikipedia - Anonymous Function

  • 0

    @Brian我一直在C#,LINQ和非LINQ运算符中使用lambdas . 例:

    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也可以传递给报价运算符,然后作为列表列表遍历 . 一些强大的宏是以这种方式制作的 .

  • 4

    想象一下,您有一个提供送货选项的餐厅,您需要在30分钟内完成订单 . 关键是客户通常不在乎你是否用汽车或赤脚骑自行车送食物,只要你保持餐点温暖和捆绑 . 因此,让我们使用匿名和定义的传输函数将此习语转换为Javascript .

    下面我们定义了我们的交付方式,我们定义了一个函数的名称:

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

    如果我们使用箭头/ lambda函数来完成这个转移怎么办:

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

    你看到客户没有差别,没有时间浪费思考如何送食物 . 只需发送它 .

    顺便说一句,我不推荐使用可乐的kebap这就是为什么上面的代码会给你错误 . 玩得开心 .

  • 56

    这个问题已得到充分回答,我不想详述 . 我想在生锈中编写数值计算时分享用法 .

    有一个lambda(匿名函数)的例子

    let f = |x: f32| -> f32 { x * x - 2.0 };
    let df = |x: f32| -> f32 { 2.0 * x };
    

    当我编写Newton-Raphson方法的模块时,它被用作一阶和二阶导数 . (如果您想知道什么是Newton-Raphson方法,请访问“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
    
  • 1

    我也明白了 . 我在JS中尝试过这个:

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

    它增加2到4然后暗示结果为6.但是我发现它有时难以阅读:(

    我也为每个函数做了一个有趣的事情:

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

    此方法将迭代数组并执行操作 - 在打印到控制台的情况下 . 现在我也明白为什么labmdas是强大的 .

  • 1

    Lambda来自Lambda Calculus并指编程中的匿名函数 .

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

    Python

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

    从Python的片段中可以看出,函数加法器接受一个参数x,并返回一个带有另一个参数y的匿名函数或lambda . 该匿名函数允许您从函数创建函数 . 这是一个简单的例子,但它应该传达lambda和闭包的力量 .

    Examples in other languages

    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
    

    Scheme

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

    Swift

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

    Haskell

    (\x y -> x + y)
    

    Javathis 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
    

    Lua

    adder = function(x)
        return function(y)
            return x + y
        end
    end
    add5 = adder(5)
    add5(1) == 6        -- true
    

    Kotlin

    val pred = { x: Int -> x % 2 == 0 }
    val result = pred(4) // true
    
  • 50

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

    我们在表达式,陈述和函数之间有明确的分离,这是数学家没有的 .

    编程中的“功能”一词也有所不同 - 我们有“功能是一系列要做的步骤”(来自拉丁语“perform”) . 在数学中,它是变量之间的相关性 .

    功能语言试图尽可能与数学公式相似,它们的意思几乎相同 . 但在其他编程语言中,我们有不同之处 .

  • 6

    lambda演算是一种一致的替代数学理论 . 在学校数学中,例如 x+y=5x−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)中,将定义相同的函数:(定义square
    (lambda(x)
    (* x x)))
    这在许多方面是不同的,但它仍然以相同的方式使用形式参数x .


    Added: http://imgur.com/a/XBHub

    lambda

  • 0

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

    我无法在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不会知道你上面的文本字符串是否拼写错误,直到它试图运行它 .

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

  • 41

    仅仅因为我在这里看不到C 11的例子,我将继续发布这个来自here的好例子 . 搜索之后,这是我能找到的最清晰的语言特定示例 .

    你好,Lambdas,版本1

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

    你好,Lambdas,版本2:

    void bar() {
        auto f = []{ printf("Hello, Lambdas\n"); };
        f();
    }
    
  • 1

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

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

  • 13

    对于没有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
    

    它现在有效,如果你坚持将两个单行合并为一个,那该怎么办?来了 lambda

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

    没有错误报告 .

    这是对 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 7. Simple statements — Python 3.6.3 documentation中有11种类型的语句

    复合语句怎么样,

    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
    

    田田,分析吧,'m'是名字,'n**2 + 2*n + 1'是值 . : 是'='的变体 .
    找到它,如果只是为了理解,一切都从作业开始,一切都是作业 .

    现在返回 lambda ,我们有一个名为'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
    

    它被称为'匿名功能'

    结论,

    • lambda 在内联函数中,您可以像在数学中一样在一条直线上编写函数

    • lambda 是匿名的

    希望这可以帮助 .

相关问题