什么是lambda(函数)?

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


#1楼

只是因为我在这里看不到C ++ 11的示例,所以我继续从这里发布这个不错的示例。 搜索之后,这是我能找到的最清晰的语言示例。

您好,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();
}

#2楼

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

#3楼

我也知道 我已经用这个在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);

在打印到控制台的情况下,此方法将迭代数组并执行操作。 现在我也明白了为什么Labmdas功能强大。


#4楼

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

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

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

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

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

#5楼

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


#6楼

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

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

蟒蛇

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

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

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

科特林

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,它是lambda的简写形式,因此您可以通过以下方式定义adder

def adder(x)
  -> y { x + y }
end

[R

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

#7楼

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

#8楼

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

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

返回大于5的数字。

number => number > 5

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


#9楼

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

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


#10楼

稍微简化了一点: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函数一样被翻译出来。


#11楼

Ruby中的lambda示例如下:

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

hello.call

将产生以下输出:

Hello
I am inside a proc

#12楼

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


#13楼

λ演算是一种一致的替代数学理论。 在学校数学中,例如看到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)中如何定义平方函数的方法:

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

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

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

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


新增: http //imgur.com/a/XBHub

拉姆达


#14楼

我在用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在运行它之前不会知道您是否在上面的文本字符串中打错字。

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


#15楼

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

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


#16楼

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

但是在编程语言中却有所不同。 这是一段被声明为“就地”的代码,可以作为“一等公民”来传递。 这个概念似乎很有用,因此几乎可以用在所有流行的现代编程语言中(请参阅lambda函数随处可见 )。


#17楼

这个问题在形式上得到了很好的回答,因此我将不尝试在此之上添加更多内容。

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

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


#18楼

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

我们在表达式,语句和函数之间有清晰的区分,而数学家则没有。

编程中的“功能”一词也有所不同-我们有“功能是要执行的一系列步骤”(拉丁语为“ perform”)。 在数学中,这与变量之间的相关性有关。

函数式语言正试图尽可能与数学公式相似,并且它们的词意味几乎相同。 但是在其他编程语言中,我们有所不同。


#19楼

对于没有计算机科学背景的人来说,计算机科学世界中的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”,“ 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

现在,如果您坚持将两条seperarte行组合为一条行之有效。 有lambda

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

没有错误报告。

乍一看lambda ,它使您可以像在数学中一样直接在计算机中一行编写函数。

我们稍后会看到。

让我们继续深入研究“分配”。

如上所示,等号=适用于简单数据(1和'值')类型和简单表达式(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中有11种类型。简单的语句-Python 3.6.3文档

复合语句怎么样

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是匿名的

希望这可以帮助。


#20楼

该问题已得到充分解答,我不想详细介绍。 我想分享在rust中编写数值计算时的用法。

有一个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

#21楼

想象一下,您有一家提供送餐服务的餐厅,而您的订单需要在30分钟内完成。 关键是客户通常不在乎您是否将食物加热并绑起来,而骑车还是赤脚骑自行车送他们的食物。 因此,让我们使用匿名和已定义的传输函数将此惯用法转换为Javascript。

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

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

如果我们使用arrow / lambda函数来完成此转移该怎么办:

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

您会看到客户没有区别,也没有时间浪费在思考如何发送食物上。 只是发送。

顺便说一句,我不建议将可乐与可乐混在一起,这就是为什么高位代码会给您带来错误的原因。 玩得开心。


#22楼

Lambda FunctionSmall Anonymous Function是一个独立的功能块,可以在代码中传递和使用。 LAMBDA在不同的编程语言不同的名字- Lambda Python科特林Closure斯威夫特 ,或BlockCObjective-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
})

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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值