什么是lambda(函数)?

时间:2020-03-05 18:40:48  来源:igfitidea点击:

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

解决方案

回答

它指的是lambda演算,这是一个只有lambda表达式的形式系统,代表了一个函数,该函数将函数作为唯一参数并返回一个函数。 Lambda演算中的所有函数都是该类型,即

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

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

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

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

回答

我们可以将其视为匿名函数,这里有更多信息:Wikipedia匿名函数

回答

Lambda来自Lambda微积分,是指编程中的匿名函数。

为什么这很酷?它允许我们编写快速抛出的函数而无需命名它们。它还提供了编写闭包的好方法。有了这种能力,我们就可以做这样的事情。

Python

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

从Python片段中可以看到,函数加法器接受一个参数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

C3.5以上

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看到这篇文章

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

a

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

回答

Lambda是内联定义的一种函数。除了lambda外,我们通常还具有某种变量类型,可以保存对函数(lambda或者其他)的引用。

例如,这是一段不使用lambda的代码:

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内部调用哪种方法以获取计算结果。

在C2.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;
    });
}

然后在C3.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);
}

回答

它是一个没有名称的函数。例如在你可以使用

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

返回大于5的数字。

number => number > 5

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

回答

我喜欢本文中对Lambda的解释:LINQ的演变及其对C#设计的影响。这对我来说很有意义,因为它显示了Lambdas的真实世界,并将其构建为实际示例。

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

回答

略微简化:lambda函数是可以传递给其他函数的函数,并且可以对其进行逻辑访问。

在Clambda中,语法通常以与匿名委托相同的方式编译为简单的方法,但也可以分解语法并读取其逻辑。

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

这也有一个"内联"功能,但是这只是编译器的魔力,Ccompiler会将其拆分为具有自动生成名称的新实例方法。

匿名方法无法读取,因此逻辑无法像lambda函数那样被翻译出来。

回答

Ruby中的lambda示例如下:

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

hello.call

将产生以下输出:

Hello
I am inside a proc

回答

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

回答

我在用lambda表达式包装时遇到了麻烦,因为我在Visual FoxPro中工作,它具有Macro替换以及ExecScript {}和Evaluate()函数,这些函数似乎具有相同的目的。

? Calculator(10, 23, "a + b")
? Calculator(10, 23, "a - b");

FUNCTION Calculator(a, b, op)
RETURN Evaluate(op)

使用正式的lambda的一个明显好处是(我认为)编译时检查:Fox在尝试运行它之前不会知道我们是否在上面的文本字符串中打错字。

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

回答

名称" 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)

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

回答

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