什么是lambda(函数)?

2024-04-26 18:07:08 发布

您现在位置:Python中文网/ 问答频道 /正文


Tags: python
3条回答

Lambda来自Lambda Calculus,在编程中引用匿名函数。

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

Python

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

从Python的片段中可以看到,函数加法器接受一个参数x,并返回一个匿名函数lambda,它接受另一个参数y。该匿名函数允许您从函数创建函数。这是一个简单的例子,但是它应该传达lambdas和闭包的强大功能。

其他语言的示例

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 = 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

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”这个名字只是一件历史文物。我们所说的只是一个值为函数的表达式。

一个简单的例子(下一行使用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)

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

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中,我们得到了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);
}

相关问题 更多 >