Go语言之匿名函数和C++的lambda表达式

欢迎关注,订阅,评论,共同学习,共同进步!

灰子学技术:

一、Go语言中的匿名函数

 

指的是不需要有名字的函数,通常定义在另外一个函数内部。

格式:

func (参数列别)(返回值列表) {

}

例子:

package main	
import (	
  "fmt"	
)	
func main() {	
  Sum := func(l, r int) (sum int) {	
    sum = l + r	
    return	
  }	
       // 备注:变量Sum作为匿名函数来使用,求和	
        fmt.Println("Hello, sum Address: sum!", &Sum, Sum(50,10))	
  return	
}	
Output:	
Hello, sum Address: sum! 0x40c128 60	

 

使用场景:

 

匿名函数通常比较短小,不希望在这个函数外部使用,这点类似与C++中的lamdba表达式。

 

补充说明:

 

匿名函数也可以实现成一个函数数组,使用者可以根据不同的indx来调用不同的匿名函数,这样的话,使用者可以根据自己的需要灵活的使用这些匿名函数。

例子:

 

package main	
import (	
  "fmt"	
)	
func main() {	
  funcs := [](func(str string) string){ // 备注:这里面实现了3个不同的函数	
    func(str string) string { return "Format 1: " + str },	
    func(str string) string { return "Format 2: " + str },	
    func(str string) string { return "Format 3: " + str },	
  }	
  for idx, fun := range funcs {	
    fmt.Println("Hello, funcs idx, result:", idx, fun("World"))	
  }	
  return	
}	
output:	
Hello, funcs idx, result: 0 Format 1: World	
Hello, funcs idx, result: 1 Format 2: World	
Hello, funcs idx, result: 2 Format 3: World	

 

二、C++中的lambda表达式

 

C++ 中的lambda表达式是在C++ 11之后才出现的,(备注:这里也只介绍C++ 11)官方文档上说它是闭包类型,笔者个人觉得可以把它理解为一个函数,不过这个函数,有下面一些特性。

 

1.是函数内部的函数,作用域在这个函数内部,出了该函数之后,不能使用。

2.lambda表达式所表示的函数,是没有名字的。

3.通常这个lambda表达式所做的事情,短小精悍。

 

为什么我们需要lambda表达式?

 

笔者觉得lambda表达式之所以存在的主要原因,是因为函数内部的一部分代码,复用率很高,但是也只是在这个函数内部使用,其他函数并不会使用。

这样就导致了一个尴尬的局面,写成一个单独的函数吧,作用范围有些广泛,不写成函数吧,函数内部要写多份相同的代码,于是lambda表达式产生了。

 

lambda的编译是当作函数来编译的,识别方法是,编译器看到[的时候就知道是lambda表达式了,然后按照lambda表达式的规则来编译。

 

如何使用lambda表达式?

 

1.lambda表达式的格式

[ captures ] ( params ) -> ret { body } // 带参数和返回值的表达式

[ captures ] ( params ) { body }  // 没有返回值的表达式

[ captures ] { body } // 无参数也无返回值的表达式

captures叫做俘获符,params是形式参数,ret 是返回类型,body表示函数体(备注:captures比较复杂,稍后介绍,其他的都比较容易理解。)

 

俘获符介绍详细如下所示:

640?wx_fmt=png

 

2. 例子

 

1) . []        //未定义变量.试图在Lambda内使用任何外部变量都是错误的.


	

	
// Example program	
#include <iostream>	
#include <string>	
int main()	
{	
  std::string name = "World!";	
  auto flag = [](int a, int b) ->bool {return a < b;};	
  bool ok = false;	
  ok = flag(2, 3);	
  std::cout << "Hello, " << name << "flag:"<< ok <<"!\n";	
  return 0;	
}	
OutPut:	
Hello, World!flag:1!	

 

640?wx_fmt=jpeg

 

 

2).  [x, &y]   //x 按值捕获, y 按引用捕获.

640?wx_fmt=jpeg

b 的数值被改变了!

 

3). [&]       //用到的任何外部变量都隐式按引用捕获

640?wx_fmt=jpeg

a, b的值都被改变了!

 

4). [=]     //用到的任何外部变量都隐式按值捕获

640?wx_fmt=jpeg

a,b可以在lambda表达式里面读取,但是不可以更改数值。

 

5). [&, x]    //x显式地按值捕获. 其它变量按引用捕获

640?wx_fmt=jpeg

a 当作&,值可以被改变,b作为值传递,不可以被改变。

 

6). [=, &z]   //z按引用捕获. 其它变量按值捕获

640?wx_fmt=jpeg

a作为引用,可以被改变,b作为传值操作,不可以被改变。

 


灰子作于二零一九年七月十八日。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值