文档库 最新最全的文档下载
当前位置:文档库 › C++11 新特性:Lambda 表达式

C++11 新特性:Lambda 表达式

C++11 新特性:Lambda 表达式
C++11 新特性:Lambda 表达式

C++11 新特性:Lambda 表达式

作者: DevBean 日期: 2012 年05 月15 日发表评论 (1)查看评论

参考文章:https://https://www.wendangku.net/doc/769436929.html,/pcarlini/entry/c_1x_tidbits_lambda_expressions

或许,Lambda 表达式算得上是C++ 11 新增特性中最激动人心的一个。这个全新的特性听起来很深奥,但却是很多其他语言早已提供(比如C#)或者即将提供(比如Java)的。简而言之,Lambda 表达式就是用于创建匿名函数的。GCC 4.5.x 和Microsoft Visual Studio 早已提供了对lambda 表达式的支持。在GCC 4.7 中,默认是不开启C++ 11 特性的,需要添

加 -std=c++11 编译参数。而VS2010 则默认开启。

为什么说lambda 表达式如此激动人心呢?举一个例子。标准C++ 库中有一个常用算法的库,其中提供了很多算法函数,比如sort() 和find()。这些函数通常需要提供一个“谓词函数predicate function”。所谓谓词函数,就是进行一个操作用的临时函数。比如find() 需要一个谓词,用于查找元素满足的条件;能够满足谓词函数的元素才会被查找出来。这样的谓词函数,使用临时的匿名函数,既可以减少函数数量,又会让代码变得清晰易读。

下面来看一个例子:

#include

#include

void abssort(float*x, unsigned N)

{

std::sort(x,

x + N,

[](float a, float b){return std::abs(a)< std::abs(b);});

}

从上面的例子来看,尽管支持lambda 表达式,但C++ 的语法看起来却很“神奇”。lambda 表达式使用一对方括号作为开始的标识,类似于声明一个函数,只不过这个函数没有名字,也就是一个匿名函数。这个匿名函数接受两个参数,a和b;其返回值是一个bool 类型的值,注意,返回值是自动推断的,不需要显式声明,不过这是有条件的!条件就是,lambda 表达式的语句只有一个return。函数的作用是比较a、b 的绝对值的大小。然后,在此例中,这个lambda 表达式作为一个闭包被传递给std::sort()函数。

下面,我们来详细解释下这个神奇的语法到底代表着什么。

我们从另外一个例子开始:

std::cout<<[](float f){return std::abs(f);}(-3.5);

输出值是什么?3.5!注意,这是一个函数对象(由lambda 表达式生成),其实参是-3.5,返回值是参数的绝对值。lambda 表达式的返回值类型是语言自动推断的,因为std::abs() 的返回值就是float。注意,前面我们也提到了,只有当lambda 表达式中的语句“足够简单”,才能自动推断返回值类型。

C++ 11 的这种语法,其实就是匿名函数声明之后马上调用(否则的话,如果这个匿名函数既不调用,又不作为闭包传递给其它函数,那么这个匿名函数就没有什么用处)。如果你觉得奇怪,那么来看看JavaScript 的这种写法:

function(){}();

function(a){}(-3.5);

C++ 11 的写法完全类似JavaScript 的语法。

如果我不想让lambda 表达式自动推断类型,或者是lambda 表达式的内容很复杂,不能自动推断怎么办?比如,std::abs(float) 的返回值是float,我想把它强制转型为int。那么,此时,我们就必须显式指定lambda 表达式返回值的类型:

std::cout<<[](float f)->int{return std::abs(f);}(-3.5);

这个语句与前面的不同之处在于,lambda 表达式的返回时不是float 而是int。也就是说,上面语句的输出值是3。返回值类型的概念同普通的函数返回值类型是完全一样的。

引入lambda 表达式的前导符是一对方括号,称为lambda 引入符(lambda-introducer)。lambda 引入符是有其自己的作用的,不仅仅是表明一个lambda 表达式的开始那么简单。lambda 表达式可以使用与其相同范围scope 内的变量。这个引入符的作用就是表明,其后的lambda 表达式以何种方式使用(正式的术语是“捕获”)这些变量(这些变量能够在lambda 表达式中被捕获,其实就是构成了一个闭包)。目前为止,我们看到的仅仅是一个空的方括号,其实,这个引入符是相当灵活的。例如:

float f0 = 1.0;

std::cout<<[=](float f){return f0 + std::abs(f);}(-3.5);

其输出值是 4.5。[=] 意味着,lambda 表达式以传值的形式捕获同范围内的变量。另外一个例子:

float f0 = 1.0;

std::cout<<[&](float f){return f0 += std::abs(f);}(-3.5);

std::cout<<'\n'<< f0 <<'\n';

输出值是 4.5 和 4.5。[&] 表明,lambda 表达式以传引用的方式捕获外部变量。那么,下一个例子:

float f0 = 1.0;

std::cout<<[=](float f) mutable {return f0 += std::abs(f);}(-3.5);

std::cout<<'\n'<< f0 <<'\n';

这个例子很有趣。首先,[=] 意味着,lambda 表达式以传值的形式捕获外部变量。C++ 11 标准说,如果以传值的形式捕获外部变量,那么,lambda 体不允许修改外部变量,对f0 的任何修改都会引发编译错误。但是,注意,我们在lambda 表达式前声明了mutable 关键字,这就允许了lambda 表达式体修改f0 的值。因此,我们的例子本应报错,但是由于有mutable 关

键字,则不会报错。那么,你会觉得输出值是什么呢?答案是,4.5 和 1.0。为什么f0 还是 1.0?因为我们是传值的,虽然在lambda 表达式中对f0 有了修改,但由于是传值的,外部的f0 依然不会被修改。

上面的例子是,所有的变量要么传值,要么传引用。那么,是不是有混合机制呢?当然也有!比如下面的例子:

float f0 = 1.0f;

float f1 =10.0f;

std::cout<<[=, &f0](float a){return f0 += f1 + std::abs(a);}(-3.5); std::cout<<'\n'<< f0 <<'\n';

这个例子的输出是14.5 和14.5。在这个例子中,f0通过引用被捕获,而其它变量,比如f1则是通过值被捕获。

下面我们来总结下所有出现的lambda 引入符:

?[] // 不捕获任何外部变量

?[=] // 以值的形式捕获所有外部变量

?[&] // 以引用形式捕获所有外部变量

?[x, &y] // x 以传值形式捕获,y 以引用形式捕获

?[=, &z] // z 以引用形式捕获,其余变量以传值形式捕获

?[&, x] // x 以值的形式捕获,其余变量以引用形式捕获

另外有一点需要注意。对于[=] 或[&] 的形式,lambda 表达式可以直接使用this 指针。但是,对于[] 的形式,如果要使用this 指针,必须显式传入:

[this](){ this->someFunc();}();

至此,我们已经大致了解了C++ 11 提供的lambda 表达式的概念。建议通过结合lambda 表达式与std::sort() 或std::for_each() 这样的标准函数来尝试使用一下吧!

Lambda表达式详细总结

(一)输入参数 在Lambda表达式中,输入参数是Lambda运算符的左边部分。它包含参数的数量可以为0、1或者多个。只有当输入参数为1时,Lambda表达式左边的一对小括弧才可以省略。输入参数的数量大于或者等于2时,Lambda表达式左边的一对小括弧中的多个参数质检使用逗号(,)分割。 示例1 下面创建一个Lambda表达式,它的输入参数的数量为0.该表达式将显示“This is a Lambda expression”字符串。 [csharp]view plain copy 1.()=>Console.WriteLine("This is a Lambda expression."); 分析2 由于上述Lambda表达式的输入参数的数量为0,因此,该Lambda表达式的左边部分的一对小括弧不能被省略。 示例2 下面创建一个Lambda表达式,它的输入参数包含一个参数:m。该表达式将计算m参数与2的乘积。 [csharp]view plain copy 1.m=>m*2; 分析2 上述Lambda表达式的输入参数省略了一对小括弧,它与“(m)=>m*2”Lambda表达式是等效的。 示例3 下面创建一个Lambda表达式,它的输入参数包含两个参数:m和n。该表达式将计算m和n 参数的乘积。 [csharp]view plain copy 1.(m,n)=>m*n;

(二)表达式或语句块 多个Lambda表达式可以构成Lambda语句块。语句块可以放到运算符的右边,作为Lambda 的主体。根据主题不同,Lambda表达式可以分为表达式Lambda和语句Lambda。语句块中可以包含多条语句,并且可以包含循环、方法调用和if语句等。 示例1 下面创建一个Lambda表达式,它的右边部分是一个表达式。该表达式计算m参数的平方值。[csharp]view plain copy 1.m=>m*n; 分析1 如果Lambda表达式的右边部分是一个语句块,那么该语句块必须被"{"和"}"包围。 示例2 下面创建一个Lambda表达式,它的输入参数包括两个参数:m和n。该表达式的右边包含2个表达式;第一个表达式计算m和n参数的乘积,结果保存为result变量;第二个表达式显示result变量的值。 [csharp]view plain copy 1.(m,n)=>{int result=m*n; Console.WriteLine(result);} 分析2 上述Lambda表达式的右边部分包含2个表达式,因此,该表达式的右边部分必须被"{"和"}"包围。 (三)查询表达式 查询表达式是一种使用查询语法表示的表达式,它用于查询和转换来自任意支持LINQ的数据源中的数据。查询表达式使用许多常见的C#语言构造,易读简洁,容易掌握。它由一组类似于SQL或XQuery的声明性语法编写的子句组成。每一个子句可以包含一个或多个C#表达式。这些C#表达式本身也可能是查询表达式或包含查询表达式。 ●查询表达式必须以from子句开头,以select或group子句结束。第一个from子句和最后一个select子句或group子句之间,可以包含一个活多个where子句、let子句、join 子句、orderby子句和group子句,甚至还可以是from子句。它包括8个基本子句,具体说明如下所示。 ●from子句:指定查询操作的数据源和范围变量。 ●select子句:指定查询结果的类型和表现形式。 ●where子句:指定筛选元素的逻辑条件。 ●let子句:引入用来临时保存查询表达式中的字表达式结果的范围变量。

C#之lambda表达式

C#的Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”。语法如下: 形参列表=>函数体 函数体多于一条语句的可用大括号括起。 类型 可以将此表达式分配给委托类型,如下所示: ? 1 2 3 delegate int del(int i); del myDelegate = x => { return x * x; }; int j = myDelegate(5); //j = 25 创建表达式目录树类型: ? 1 2 3 using System.Linq.Expressions; // ... Expression = x => x * x; => 运算符具有与赋值运算符 (=) 相同的优先级,并且是右结合运算符。 Lambda 用在基于方法的 LINQ 查询中,作为诸如 Where 和 Where 等标准查询运算符方法的参数。 使用基于方法的语法在 Enumerable 类中调用 Where 方法时(像在 LINQ to Objects 和 LINQ to XML 中那样),参数是委托类型 System..::.Func<(Of <(T, TResult>)>)。使用 Lambda 表达式创建委托最为方便。例如,当您在 System.Linq..::.Queryable 类中调用相同的方法时(像在 LINQ to SQL 中那样),则参数类型是 System.Linq.Expressions..::.Expression,其中 Func 是包含至多五个输入参数的任何 Func 委托。同样,Lambda 表达式只是一种用于构造表达式目录树的非常简练的方式。尽管事实上通过 Lambda 创建的对象的类型是不同的,但 Lambda 使得 Where 调用看起来类似。 在前面的示例中,请注意委托签名具有一个 int 类型的隐式类型输入参数,并返回 int 。可以将 Lambda 表达式转换为该类型的委托,因为该表达式也具有一个输入参数 (x),以及一个编译器可隐式转换为 int 类型的返回值。(以下几节中将对类型推理进行详细讨论。)使用输入参数 5 调用委托时,它将返回结果 25。 在 is 或 as 运算符的左侧不允许使用 Lambda 。 适用于匿名方法的所有限制也适用于 Lambda 表达式。有关更多信息,请参见匿名方法(C# 编程指南)。 特殊 下列规则适用于 Lambda 表达式中的变量范围:

python语言零基础入门-函数

1、函数的基本概念及调用(ppt) 2、自定义函数 如何创建函数?def语句 In [2]: # 定义函数 def f(x): if x <5: print('输入值小于5') else: print('输入值大于等于5') # 定义函数,其中x是参数(局部变量)f(10) # 运行函数 输入值大于等于5 In [3]: # 关于retuen def f1(x): y =2**x # 没有return def f2(x): y =2**x return y # 含有return print(f1(2),f2(2)) # return语句退出函数,并返回一个表达式。不带参数值的return语句返回None None 4 In [4]: # 默认参数 def f(x,n =2): return(x**n) print(f(10)) print(f(10,3)) # n = 2,这里n的默认值为2,如果不输入则以默认值为主 100 1000

小作业 ① 函数f (x ),输入一个字符串,分别print 出每个字母 ② f(x,y,z),函数内部算法:生成 ((x+y)*(x-y))**z ③ 编写一个求平均值的函数 f(*m) ④ 定义一个函数,用于求矩形面积、圆形面积 ⑤ 定义一个函数,函数的作用是把输入的列表变成一连串字典的key ,并生成字典,需要用input 输入 3、局部变量及全局变量 定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。 局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中 In [6]: (1,) ('a', 'b') (1, 2, 3, [44, 33]) ('a', 'b') 请输入一个数字:60 函数内为局部变量:呵呵哒 函数外为全局变量:60 # 可变参数 def f (*x): print (x) return x f(1) f('a','b') f(1,2,3,[44,33]) print (type (f('a','b'))) # 通过*来定义可变参数# 默认会把可变参数传入一个元祖! # 演示案例 def f (m): m = '呵呵哒' # 函数作用:把输入变量指向“呵呵哒” print ("函数内为局部变量:%s" % m) a = input ('请输入一个数字:') f(a) print ("函数外为全局变量:%s" % a) # f (m )中,m 是函数的参数,f(x)是吧x 的值赋予了m ,但x 值自己本身不受影响,所以执行函数后,是在函数局部# 什么是局部变量? → 当函数定义内声明变量的时候,它们与函数外具有相同名称的其他变量没有任何关系!# 即变量名称对于函数来说是“局部”的。这称为变量的作用域。所有变量的作用域是它们被定义的块,从它们的

Lambda表达式详细总结

lambda简介 lambda运算符:所有的lambda表达式都是用新的lambda运算符 " => ",可以叫他,“转到”或者“成为”。运算符将表达式分为两部分,左边指定输入参数,右边是lambda的主体。 lambda表达式: 1.一个参数:param=>expr 2.多个参数:(param-list)=>expr https://www.wendangku.net/doc/769436929.html,/wangboxian/article/details/41963205 Lambda表达式详细总结 (一)输入参数 在Lambda表达式中,输入参数是Lambda运算符的左边部分。它包含参数的数量可以为0、1或者多个。只有当输入参数为1时,Lambda表达式左边的一对小括弧才可以省略。输入参数的数量大于或者等于2时,Lambda表达式左边的一对小括弧中的多个参数质检使用逗号(,)分割。 示例1 下面创建一个Lambda表达式,它的输入参数的数量为0.该表达式将显示“This is a Lambda expression”字符串。 [csharp] view plaincopyprint? ()=>Console.WriteLine("This is a Lambda expression."); ()=>Console.WriteLine("This is a Lambda expression."); 分析2 由于上述Lambda表达式的输入参数的数量为0,因此,该Lambda表达式的左边部分的一对小括弧不能被省略。 示例2 下面创建一个Lambda表达式,它的输入参数包含一个参数:m。该表达式将计算m参数与2的乘积。 [csharp] view plaincopyprint? m=>m*2; m=>m*2; 分析2 上述Lambda表达式的输入参数省略了一对小括弧,它与“(m)=>m*2”Lambda表达式是等效的。 示例3

Lambda 表达式

本文导读:“Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式树类型。所有 Lambda 表达式都使用 Lambda 运算符 =>。该Lambda 运算符的左边是输入参数(如果有),右边包含表达式或语句块。 lambda表达式使得函数可以在使用的地方声明,并且可以在lambda函数中使用lambda函数之外的数据。 一、lambda运算符 所有的lambda表达式都是用新的lambda运算符 " => ",可以叫他,“转到”或者“成为”。运算符将表达式分为两部分,左边指定输入参数,右边是lambda的主体。 使用Lambda表达式,当编译器编译时,Lambda表达式同样会被编译成一个匿名方法进行相应的操作,但是与匿名方法相比,Lambda表达式更容易阅读。 比较Lambda表达式和匿名方法,在匿名方法中,"("、")"内是方法的参数的集合,这就对应了Lambda表达式中的"(参数列表)",而匿名方法中"{"、"}"内是方法的语句块,这对应了Lambda表达式中"=>"符号右边的表达式或语句块项。 二、lambda表达式语法 Lambda表达式可以有多个参数、一个参数,或者没有参数。 格式: (参数列表)=>表达式或语句块 表现形式为 1.一个参数:param=>expr 2.多个参数:(param-list)=>expr Lambda表达式的格式实例 1(x, y) => x * y //多参数,隐式类型=> 表达式 2x => x * 5 //单参数,隐式类型=>表达式

3x => { return x * 5; } //单参数,隐式类型=>语句块 4(int x) => x * 5 //单参数,显式类型=>表达式 5(int x) => { return x * 5; } //单参数,显式类型=>语句块 6() => Console.WriteLine() //无参数 三、Lambda表达式与匿名方法的对比实例 1、Sort方法 C# 代码复制 List list=new List(); var numbers = new []{ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; list.AddRange(numbers); list.Sort(delegate (int a, int b) { return https://www.wendangku.net/doc/769436929.html,pareTo(b); } ); //use lambda list.Sort((a,b)=>https://www.wendangku.net/doc/769436929.html,pareTo(b)); 2、ConvertAll方法 C# 代码复制 ListdoubleList =list.ConvertAll(delegate(int i) { return i*2; }); //use lambda var doubleList2=list.ConvertAll(i=>i*2);

C++11 新特性:Lambda 表达式

C++11 新特性:Lambda 表达式 作者: DevBean 日期: 2012 年05 月15 日发表评论 (1)查看评论 参考文章:https://https://www.wendangku.net/doc/769436929.html,/pcarlini/entry/c_1x_tidbits_lambda_expressions 或许,Lambda 表达式算得上是C++ 11 新增特性中最激动人心的一个。这个全新的特性听起来很深奥,但却是很多其他语言早已提供(比如C#)或者即将提供(比如Java)的。简而言之,Lambda 表达式就是用于创建匿名函数的。GCC 4.5.x 和Microsoft Visual Studio 早已提供了对lambda 表达式的支持。在GCC 4.7 中,默认是不开启C++ 11 特性的,需要添 加 -std=c++11 编译参数。而VS2010 则默认开启。 为什么说lambda 表达式如此激动人心呢?举一个例子。标准C++ 库中有一个常用算法的库,其中提供了很多算法函数,比如sort() 和find()。这些函数通常需要提供一个“谓词函数predicate function”。所谓谓词函数,就是进行一个操作用的临时函数。比如find() 需要一个谓词,用于查找元素满足的条件;能够满足谓词函数的元素才会被查找出来。这样的谓词函数,使用临时的匿名函数,既可以减少函数数量,又会让代码变得清晰易读。 下面来看一个例子: #include #include void abssort(float*x, unsigned N) { std::sort(x, x + N, [](float a, float b){return std::abs(a)< std::abs(b);}); } 从上面的例子来看,尽管支持lambda 表达式,但C++ 的语法看起来却很“神奇”。lambda 表达式使用一对方括号作为开始的标识,类似于声明一个函数,只不过这个函数没有名字,也就是一个匿名函数。这个匿名函数接受两个参数,a和b;其返回值是一个bool 类型的值,注意,返回值是自动推断的,不需要显式声明,不过这是有条件的!条件就是,lambda 表达式的语句只有一个return。函数的作用是比较a、b 的绝对值的大小。然后,在此例中,这个lambda 表达式作为一个闭包被传递给std::sort()函数。 下面,我们来详细解释下这个神奇的语法到底代表着什么。 我们从另外一个例子开始: std::cout<<[](float f){return std::abs(f);}(-3.5); 输出值是什么?3.5!注意,这是一个函数对象(由lambda 表达式生成),其实参是-3.5,返回值是参数的绝对值。lambda 表达式的返回值类型是语言自动推断的,因为std::abs() 的返回值就是float。注意,前面我们也提到了,只有当lambda 表达式中的语句“足够简单”,才能自动推断返回值类型。

Lambda

Lambda演算 Lambda演算是一个形式系统,它被设计出来用来研究函数定义,函数应用和递归。它是在二十世纪三十年代由Alonzo Church 和 Stephen Cole Kleene发明的。Church在1936年使用lambda演算来证明了判定问题是没有答案的。Lambda演算可以用来清晰的定义什么是一个可计算的函数。两个lambda演算表达式是否相等的问题不能够被一个通用的算法解决,这是第一个问题,它甚至排在停机问题之前。为了证明停机问题是没有答案的,不可判定性能够被证明。Lambda演算对于函数式编程语言(例如lisp)有重大的影响。 同时,数理逻辑中对于lambda演算的介绍就简单得多: λ-演算可以说是最简单、最小的一个形式系统。它是在二十世纪三十年代由Alonzo Church 和Stephen Cole Kleene发明的。至今,在欧洲得到了广泛的发展。可以说,欧洲的计算机科学是从λ-演算开始的,而现在仍然是欧洲计算机科学的基础,首先它是函数式程序理论的基础,而后,在λ-演算的基础上,发展起来的π-演算、χ-演算,成为近年来的并发程序的理论工具之一,许多经典的并发程序模型就是以π-演算为框架的。 这里不由得想起一位我尊敬的老师的博士毕业论文就是关于π-演算的,可惜这位老师已经去别的学校了。 Lambda演算表达了两个计算机计算中最基本的概念“代入”和“置换”。“代入”我们一般理解为函数调用,或者是用实参代替函数中的形参;“置换”我们一般理解为变量换名规则。后面会讲到,“代入”就是用lambda演算中的β-归约概念。而“替换”就是lambda演算中的α-变换。Lambda演算系统的形式化定义 维基百科全书上面的对于lambda演算的定义不是很正规,但是说明性的文字较多。而数理逻辑中的定义很严密,不过没有说明不容易理解。我尽可能把所有资料结合起来说明lambda演算系统的定义。字母表 lambda演算系统中合法的字符如下: 1. x1,x2,x3,…变元(变元的数量是无穷的,不能在有限步骤内穷举,这个很重要,后面有定理是根据这一点证明的) 2. à 归约 3. =等价 4. λ,(,)(辅助工具符号,一共有三个,λ和左括号右括号) 所有能够在lambda演算系统中出现的合法符号只有以上四种,其他符号都是非法的。例如λx.x+2,如果没有其他对于+符号的说明,那么这就是一个非法的λ演算表达式。 λ-项 λ-项在一些文章中也称为λ表达式(lambda expression),它是由上面字母表中的合法字符组成的表达式,合法的表达式组成规则如下: 1. 任一个变元是一个项 2. 若M,N是项,则(MN)也是一个项(function application,函数应用) 3. 若M是一个项,而x是一个变元,则(λx.M)也是一个项(function abstraction,函数抽象) 4. 仅仅由以上规则归纳定义得到的符号串是项 说明1:λ-项是左结合的,意思就是若f x y都是λ-项,那么f x y=(f x) y 说明2:(λx.M)这样的λ-项被称为函数抽象,原因是它常常就是一个函数的定义,函数的参数就是变量x,函数体就是M,而函数名称则是匿名的。用一个不恰当的比喻来说,我们通常认为的函数

C#委托、Lambda表达式

委托、Lambda表达式 1. 委托 (2) (1) 委托的本质 (2) (2) 使用委托的示例 (2) (3) 委托的Invoke与BeginInvoke方法 (2) 1、 Invoke方法 (2) 2、 BeginInvoke方法 (2) 3、委托的EndInvoke方法 (3) (4) Action、Func与Predicate(泛型委托) (3) 1、 Action无返回值的泛型委托 (3) 2、 Func带有返回值的泛型委托 (4) 3、 Predicate委托(常用于集合参数) (4) (5) 多播委托 (4) (6) 使用委托定义匿名方法 (5) 2. Lambda表达式 (5) (1) Lambda表达式本质 (5) (2) Lambda表达式使用示例 (5) (3) Lambda表达式语法 (6) 1、表达式Lambda语法(参数语法) (6) 2、语句Lambda语法(函数体语法) (6) 3、类型猜测 (6) 4、 Lambda式中的变量作用域 (6) 作者:李志伟 时间:2014-01-18

1.委托 (1)委托的本质 委托实际上就是指向函数的指针。在C#中委托是一种类型,定义一个委托就是定义一个新的类,它与类的地位是一样的,所以可以定义类的地方都可以定义委托! 实际上,使用delegate关键字定义的委托继承了System.MulticastDelegate类,而System.MulticastDelegate类又继承了System.Delegate。 Delegate:表示委托,委托是一种数据结构,它引用静态方法或引用类实例及该类的实例方法。 MulticastDelegate:表示多路广播委托;即,其调用列表中可以拥有多个元素的委托。 (2)使用委托的示例 delegate string DelegateMethod(int a, int b);//定义委托 class Program { static void Main(string[] args) { DelegateMethod dm = new DelegateMethod(Method);//或:DelegateMethod dm = Method Console.WriteLine(dm(10, 20));//执行委托 Console.Read(); } private static string Method(int a, int b) { return"相加结果:" + (a + b); } } (3)委托的Invoke与BeginInvoke方法 1、Invoke方法 实际上,给委托实例提供圆括号与调用委托的Invoke方法效果完全相同: delegate string DelegateMethod(int a, int b);//定义委托 class Program { static void Main(string[] args) { DelegateMethod dm = Method; Console.WriteLine(dm.Invoke(10, 20));//执行委托 Console.Read(); } private static string Method(int a, int b) { return"相加结果:" + (a + b); } } 2、BeginInvoke方法 调用委托实例的BeginInvoke方法就是开启一个新的线程执行委托实例指向的方法。 delegate void DelegateMethod(int a, int b);//定义委托 class Program { static void Main(string[] args) { DelegateMethod dm = Method; for (int i = 0; i < 10; i++) { dm.BeginInvoke(i, 20, null, null);//异步调用委托 } Console.Read(); } private static void Method(int a, int b) {

基于Lambda架构的股票市场事件处理引擎实践

基于Lambda架构的股票市场事件处理引擎实践 CEP(Complex Event Processing)是证券行业很多业务应用的重要支撑技术。CEP的概念本身并不新鲜,相关技术已经被运用超过15年以上,但是证券界肯定是运用CEP技术最为充分、最为前沿的行业之一,从算法交易(algorithmic trading)、风险管理(risk management)、关键时刻管理(Moment of Truth – MOT)、委托与流动性分析(order and liquidity analysis)到量化交易(quantitative trading)乃至向投资者推送投资信号(signal generation)等等,不一而足。 CEP技术通常与Time-series Database(时序数据库)结合,最理想的解决方案是CEP技术平台向应用提供一个历史序列(historical time-series)与实时序列(real-time series)无差异融合的数据流连续体(continuum)- 对于证券类应用而言,昨天、上周、上个月的数据不过是当下此刻数据的延续,而处理算法却是无边际的 – 只要开发者能构想出场景与模型。 广发证券的IT研发团队,一直关注Storm、Spark、Flink等流式计算的开源技术,也经历了传统Lambda架构的技术演进,在Kappa 架构的技术尚未成熟之际,团队针对证券行业的技术现状与特点,采用改良的Lambda架构实现了一个CEP引擎,本文介绍了此引擎的架构并分享了一些股票业务较为有趣的应用场景,以飨同好。 随着移动互联和物联网的到来,大数据迎来了高速和蓬勃发展时期。一方面,移动互联和物联网产生的大量数据为孕育大数据技术提供了肥沃的土壤;一方面,各个公司为了应对大数据量的挑战,也急切的需要大数据技术解决生产实践中的问题。短时间内各种技术层出不穷,在这个过程中Hadoop脱颖而出,并营造了一个丰富的生态圈。虽然大数据一提起Hadoop,好像有点老生常谈,甚至觉得这个技术已经过时了,但是不能否认的是Hadoop的出现确实有非凡的意义。不管是它分布式处理数据的理念,还是高可用、容错的处理都值得好好借鉴和学习。 刚开始,大家可能都被各种分布式技术、思想所吸引,一头栽进去,掉进了技术的漩涡,不能自拔。一方面大数据处理技术和系统确实复杂、繁琐;另一方面大数据生态不断的推陈出新,新技术和新理念层出不穷,确实让人目不暇接。如果想要把生态圈中各个组件玩精通确实不是件容易的事情。本人一开始也是深陷其中,皓首穷经不能自拔。但腾出时间,整理心绪,回头反顾,突然有种释然之感。大数据并没有大家想象的那么神秘莫测与复杂,从技术角度看无非是解决大数据量的采集、计算、展示的问题。 因此本文参考Lambda/Kappa架构理念,提出了一种有行业针对性的实现方法。尽量让系统层面更简单,技术更同构,初衷在让大家聚焦在大数据业务应用上来,从而真正让大数据发挥它应有的价值。 1、 背景 Lambda架构是由Storm的作者Nathan Marz 在BackType和Twitter多年进行分布式大数据系统的经验总结提炼而成,用数学表达式可以表示如下: batch view = function(all data) realtime view = function(realtime view,new data) query = function(batch view .realtime view) 逻辑架构图如下:

Java8 Lambda表达式

怒学Java 8 by bjpengpeng@https://www.wendangku.net/doc/769436929.html, 函数式编程 课本上说编程有两种模式,面向过程的编程以及面向对象的编程,其实在面向对象编程之前还出现了面向函数的编程(函数式编程) ,以前一直被忽略、不被重视,现在从学术界已经走向了商业界,对函数编程语言的支持目前有Scala、Erlang、F#、Python、Php、Java、Javascript等,有人说他将会是编程语言中的下一个主流... Lambda表达式 为什么需要Lambda表达式 1.使用Lambda表达式可以使代码变的更加紧凑,例如在Java中实现一个线程,只输出一个字符串Hello World!,我们的代码如下所示: public static void main(String[] args) throws Exception { new Thread(new Runnable() { @Override public void run() { System.out.println("Hello World!"); } }).start(); TimeUnit.SECONDS.sleep(1000); } 使用Lambda表达式之后代码变成如下形式: public static void main(String[] args) throws Exception { new Thread(() -> System.out.println("Hello World!")).start(); TimeUnit.SECONDS.sleep(1000); } 是不是代码变的更紧凑了~,其他的例如各种监听器,以及事件处理器等都可以用这种方式进行简化。 2.修改方法的能力,其实说白了,就是函数中可以接受以函数为单元的参数,在C/C++中就是函数指针,在Java中就是Lambda表达式,例如在Java中使用集合类对一个字符串按字典序列进行排序,代码如下所示: public static void main(String[] args) { String []datas = new String[] {"peng","zhao","li"}; Arrays.sort(datas); Stream.of(datas).forEach(param -> System.out.println(param)); } 在上面代码中用了Arrays里的sort方法,现在我们不需要按字典排序,而是按字符串的长度进行排序,代码如下所示: public static void main(String[] args) { String []datas = new String[] {"peng","zhao","li"}; Arrays.sort(datas,(v1 , v2) -> https://www.wendangku.net/doc/769436929.html,pare(v1.length(), v2.length())); Stream.of(datas).forEach(param ->

10个Java8Lambda表达式经典示例

10个Java 8 Lambda表达式经典示例Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动。特性之一便是随同发布的lambda表达式,它将允许我们将行为传到函数里。在Java 8之前,如果想将行为传入函数,仅有的选择就是匿名类,需要6行代码。而定义行为最重要的那行代码,却混在中间不够突出。Lambda表达式取代了匿名类,取消了模板,允许用函数式风格编写代码。这样有时可读性更好,表达更清晰。在Java生态系统中,函数式表达与对面向对象的全面支持是个激动人心的进步。 将进一步促进并行第三方库的发展,充分利用多核CPU。尽管业界需要时间来消化Java 8,但我认为任何严谨的Java开发者都不应忽视此次Java发布的核心特性,即lambda表达式、函数式接口、流API、默认方法和新的Date以及Time API。作为开发人员,我发现学习和掌握lambda表达式的最佳方法就是勇于尝试,尽可能多练习lambda表达式例子。鉴于受Java 8发布的影响最大的是Java集合框架(Java Collections framework),所以最好练习流API和lambda表达式,用于对列表(Lists)和集合(Collections)数据进行提取、过滤和排序。我一直在进行关于Java 8的写作,过去也曾分享过一些资源来帮助大家掌握Java 8。本文分享在代码中最有用的10个lambda表达式的使用方法,这些例子都短小精悍,将帮助你快速学会lambda表达式。 Java 8 lambda表达式示例 我个人对Java 8发布非常激动,尤其是lambda表达式和流API。越来越多的了解它们,我能写出更干净的代码。虽然一开始并不是这样。第一次看到用lambda表达式写出来的Java代码时,我对这种神秘的语法感到非常失望,认为它们把Java搞得不可读,但我错了。花了一天时间做了一些lambda表达式和流API示例的练习后,我开心的看到了更清晰的Java代码。这有点像学习泛型,第一次见的时候我很讨厌它。我甚至继续使用老版Java 1.4来处理集合,直到有一天,朋友跟我介绍了使用泛型的好处(才意识到它的好处)。所以基本立场就是,不要畏惧lambda表达式以及方法引用的神秘语法,做几次练习,从集合类中提取、过滤数据之后,你就会喜欢上它。下面让我们开启学习Java 8 lambda表达式的学习之旅吧,首先从简单例子开始。 例1、用lambda表达式实现Runnable 我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名类,而实现Runnable 接口是匿名类的最好示例。看一下Java 8之前的runnable实现方法,需要4行代码,而使用lambda表达式只需要一行代码。我们在这里做了什么呢?那就是用() -> {}代码块替代了整个匿名类。 // Java 8之前: new Thread(new Runnable() { Override public void run() { System.out.println("Before Java8, too much code for too little to do"); } }).start(); //Java 8方式: new Thread( () -> System.out.println("In Java8, Lambda expression

Java 8 Lambda表达式

深入学习Java 8 Lambda(语言篇——lambda 表达式的深入学习) 关于 1. 深入理解Java 8 Lambda(语言篇——lambda,方法引 用,目标类型和默认方法) 2. 深入理解Java 8 Lambda(类库篇——Streams API, Collector 和并行) 3. 深入理解 Java 8 Lambda(原理篇——Java 编译器如何 处理 lambda) 本文是深入理解 Java 8 Lambda 系列的第一篇,主要介绍 Java 8新增的语言特性(比如lambda 和方法引用),语言概念(比如目标类型和变量捕获)以及设计思路。 本文是对Brian Goetz的State of Lambda一文的翻译,那么问题来了: 为什么要翻译这个系列? 1. 工作之后,我开始大量使用 Java 2. 公司将会在不久的未来使用 Java 8 3. 作为资质平庸的开发者,我需要打一点提前量,以免到时拙 计 4. 为了学习Java 8(主要是其中的lambda 及相关库),我 先后阅读了Oracle的官方文档,Cay Horstmann(Core Java的作者)的Java 8 for the Really Impatient和 Richard Warburton的Java 8 Lambdas 5. 但我感到并没有多大收获,Oracle的官方文档涉及了 lambda 表达式的每一个概念,但都是点到辄止;后两本书 (尤其是Java 8 Lambdas)花了大量篇幅介绍Java lambda 及其类库,但实质内容不多,读完了还是没有对

6. 7. 8. 警告(Caveats) 如果你不知道什么是函数式编程,或者不了解map,filter,reduce这些常用的高阶函数,那么你不适合阅读本文,请先学习函数式编程基础(比如这本书)。 State of Lambda by Brian Goetz The high-level goal of Project Lambda is to enable programming patterns that require modeling code as data to be convenient and idiomatic in Java. 关于 本文介绍了 Java SE 8 中新引入的 lambda 语言特性以及这些特性

相关文档