【问题标题】:What is a lambda (function)?什么是 lambda(函数)?
【发布时间】:2010-09-06 04:49:23
【问题描述】:

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

【问题讨论】:

  • amda表情解释here漂亮。
  • 请参阅 this 了解 lambda 函数在各种语言中的外观,以及它们是在哪一年以这些语言引入的。

标签: lambda language-agnostic computer-science terminology theory


【解决方案1】:

Lambda Function 或 Small Anonymous Function 是一个独立的功能块,可以在您的代码中传递和使用。 Lambda 在不同的编程语言中有不同的名称——Python 和 Kotlin 中的 Lambda、Swift 中的 Closure 或 Swift 中的 Block strong>C 和 Objective-C。尽管 lambda 在这些语言中的含义非常相似,但有时会略有不同。

让我们看看 Closure (Lambda) 在 Swift 中是如何工作的:

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

3。内联闭包表达式

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"]

【讨论】:

    【解决方案2】:

    Lambda为大家讲解:

    Lambda 是一个匿名函数。这意味着 lambda 是 Python 中的一个函数对象,之前不需要引用。让我们在这里考虑这段代码:

    def name_of_func():
        #command/instruction
        print('hello')
    
    print(type(name_of_func))   #the name of the function is a reference
                                #the reference contains a function Object with command/instruction
    

    为了证明我的提议,我打印出返回我们的 name_of_func 类型:

    <class 'function'>
    

    一个函数必须有一个接口,但一个接口说明需要包含一些东西。这是什么意思?让我们稍微接近一下我们的函数,我们可能会注意到,除了函数的名称之外,我们还需要解释更多细节以了解函数是什么。

    一个普通的函数会用语法"def"定义,然后我们输入名字并用"()来设置接口" 并以语法 ":" 结束我们的定义。现在我们使用指令/命令进入函数体。

    所以让我们在这里考虑这段代码:

    def print_my_argument(x):
        print(x)
    
    
    print_my_argument('Hello')
    

    在这种情况下,我们运行名为“print_my_argument”的函数并通过接口传递参数/参数。输出将是:

    Hello
    

    既然我们知道了什么是函数以及函数的架构是如何工作的,那么我们可以看看匿名函数。让我们在这里考虑这段代码:

    def name_of_func():
        print('Hello')
    
    
    
    lambda: print('Hello')
    

    这些函数对象几乎相同,除了上面的常规函数​​有一个名称,而另一个函数是匿名的。让我们仔细看看我们的匿名函数,以了解如何使用它。

    所以让我们在这里考虑这段代码:

    def delete_last_char(arg1=None):
        print(arg1[:-1])
    
    string = 'Hello World'
    delete_last_char(string)
    
    f = lambda arg1=None: print(arg1[:-1])
    f(string)
    

    所以我们在上面的代码中所做的就是再次编写一个常规函数和一个匿名函数。我们已经分配给 var 的匿名函数,这与给该函数命名几乎相同。无论如何,输出将是:

    Hello Worl
    Hello Worl
    

    为了充分证明 lambda 是一个函数对象并且不只是模仿一个函数,我们在这里运行这段代码:

    string = 'Hello World'
    f = lambda arg1=string: print(arg1[:-1])
    f()
    print(type(f))
    

    输出将是:

    Hello Worl
    <class 'function'>
    

    最后但同样重要的是,您应该知道 python 中的每个函数都需要返回一些内容。如果函数体中没有定义任何内容,则默认返回 None 。看看这里的这段代码:

    def delete_last_char(arg1):
        print(arg1[:-1])
    
    string = 'Hello World'
    x = delete_last_char(string)
    
    f = lambda arg1=string: print(arg1[:-1])
    x2 = f()
    
    print(x)
    print(x2)
    

    输出将是:

    Hello Worl
    Hello Worl
    None
    None
    

    【讨论】:

      【解决方案3】:

      lambda 函数可以接受任意数量的参数,但它们只包含一个表达式。 ... Lambda 函数可用于返回函数对象。 从语法上讲,lambda 函数仅限于单个表达式。

      【讨论】:

      • "lambda 函数仅限于单个表达式" - 这实际上不是真的。 C# 有 Statement lambda,您可以在其中将代码块作为主体放置,对于许多其他语言也是如此。
      【解决方案4】:

      Ruby 中的 lambda 示例如下:

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

      将生成以下输出:

      Hello
      I am inside a proc
      

      【讨论】:

        【解决方案5】:

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

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

        Python

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

        从 Python 的 sn-p 中可以看出,函数加法器接受一个参数 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
        

        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 = fn () => $a + $b;
        
        echo $lambda();
        

        Haskell

        (\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
        

        Lua

        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
        

        R

        adder <- function(x) {
          function(y) x + y
        }
        add5 <- adder(5)
        add5(1)
        #> [1] 6
        

        【讨论】:

        • 那么,lambda 函数和a functor 之间有什么区别?
        • @Maxpm 仿函数可以是具有实例字段和函数的标准对象,而 lambda 函数通常只包含一行指令。当然,这可能因语言而异。
        • 我认为说 lambda 函数与匿名函数相同并不一定准确。对于 JavaScript 等某些语言,lambda 表达式是匿名函数的一种特定形式。您给出的 JavaScript 示例是一个没有 lambda 语法的匿名函数,而您给出的 JavaScript (ES6) 示例是一个 lambda 表达式。
        • @KyleDelaney 确实,匿名不是成为 lambda 的必要条件,确实有 lambda 函数不是匿名的,正如您在示例中指出的那样
        • @AliAnkarali 或习惯使用 ruby​​s lambda ;)
        【解决方案6】:

        假设您有一家提供外卖选项的餐厅,而您的订单需要在 30 分钟内完成。关键是客户通常不在乎你是骑自行车还是光脚送他们的食物,只要你保持食物温暖和捆绑。因此,让我们将这个成语转换为具有匿名和定义运输功能的 Javascript。

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

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

        如果我们使用箭头/lambda 函数来完成这种传输会怎样:

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

        您会发现客户没有区别,也没有浪费时间考虑如何发送食物。发送就行了。

        顺便说一句,我不推荐带可乐的烤肉串,这就是为什么上面的代码会给你错误。玩得开心。

        【讨论】:

          【解决方案7】:

          因为我在这里看不到 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();
          }
          

          【讨论】:

            【解决方案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
            

            【讨论】:

              【解决方案9】:

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

              Lisp 使用 lambda 概念来命名它的匿名函数字面量。这个 lambda 表示一个函数,它接受两个参数 x 和 y,并返回它们的乘积:

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

              它可以像这样内联应用(计算为 50):

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

              【讨论】:

              • 我认为您对λ : λ -&gt; λ 的使用令人困惑(实际上是无效的)。
              【解决方案10】:

              对于没有计算机科学背景的人来说,计算机科学界的 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中有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' 是值。: 是 '=' 的变体。
              找到它,如果只是为了理解,一切从赋值开始,一切都是赋值。

              现在返回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
              

              称为“匿名函数”

              总之,

              1. lambda 在内联函数中,使您可以像在数学中一样在一条直线上编写函数
              2. lambda 是匿名的

              希望,这会有所帮助。

              【讨论】:

                【解决方案11】:

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

                我们对表达式、语句和函数有明确的区分,这是数学家所没有的。

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

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

                【讨论】:

                  【解决方案12】:

                  这个问题已经正式回答了,所以我不会尝试添加更多。

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

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

                  【讨论】:

                    【解决方案13】:

                    在 CS 上下文中,lambda 函数是一个抽象的数学概念,用于解决数学表达式的符号求值问题。在这种情况下,lambda 函数与lambda term 相同。

                    但在编程语言中,情况有所不同。这是一段被声明为“就地”的代码,可以作为“一等公民”传递。这个概念似乎很有用,因此它进入了几乎所有流行的现代编程语言(参见lambda functions everwhere 帖子)。

                    【讨论】:

                      【解决方案14】:

                      例如,在 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]()()();
                      

                      【讨论】:

                        【解决方案15】:

                        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:

                        这里是如何在命令式中定义 square 函数 编程语言(C):

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

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

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

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


                        已添加: http://imgur.com/a/XBHub

                        【讨论】:

                          【解决方案16】:

                          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 中我们得到了 lambdas,这使得代码更短:

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

                          【讨论】:

                          • 可以简单地使用Func&lt;int, int&gt;,而不是显式定义委托Op
                          • 我建议Console.WriteLine("Calculator: op " + op.Method.Name + " (" + a + ", " + b + ") = " + op(a, b));作为第一个例子。
                          • 公认的答案在帮助许多不同语言的人方面令人惊叹,但我觉得这个答案有助于我更好地理解 lambda 的优势,以及它们与标准函数的不同之处。我可以在这里清楚地看到 lambda 在获得类似结果方面优于以前的方法。
                          • 感谢您的示例,拥有一个更复杂的函数有助于理解 lambdas 的优势,而不是看起来您没有得到太多优化的简单函数
                          • 这是使用 lambda 函数的第一个解释/示例,它让我明白了含义。谢谢
                          【解决方案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)
                          

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

                          【讨论】:

                            【解决方案18】:

                            由于我在 Visual FoxPro 中工作,它具有宏替换以及 ExecScript{} 和 Evaluate() 函数,这似乎具有相同的目的,因此我很难理解 lambda 表达式。

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

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

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

                            【讨论】:

                            • Visual Fox Pro。这让我回到了岁月。
                            【解决方案19】:

                            @Brian 我一直在 C#、LINQ 和非 LINQ 运算符中使用 lambda。示例:

                            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 也可以传递给引号运算符,然后作为列表的列表进行遍历。一些强大的宏就是这样制作的。

                            【讨论】:

                              【解决方案20】:

                              有点过于简单了: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; 
                                  } );
                              

                              这也有一个“内联”函数,但这次它只是编译器的魔法——C# 编译器会将其拆分为一个具有自动生成名称的新实例方法。

                              无法读取匿名方法,因此无法将逻辑转换为 lambda 函数。

                              【讨论】:

                                【解决方案21】:

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

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

                                【讨论】:

                                  【解决方案22】:

                                  这是一个没有名字的函数。例如在c#中你可以使用

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

                                  返回大于 5 的数字。

                                  number => number > 5
                                  

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

                                  【讨论】:

                                    【解决方案23】:

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

                                    【讨论】:

                                      猜你喜欢
                                      • 2021-01-19
                                      • 2018-08-06
                                      • 2017-05-28
                                      • 1970-01-01
                                      • 2021-02-03
                                      相关资源
                                      最近更新 更多