lambda表达式杂谈
上面的数据存放着一组人员姓名、年龄、性别相关的信息。 现在有一个需求, 获得年龄20岁以上,性别为女的人的姓名。 看到需求后, 很多人脑袋中产生的解决方案可能是这样的
代码执行的结果是[“夏香”,“秋香”]
很好,结果正确,考试的话肯定给满分。
但是这种实现方法有点过时,不潇洒,现在流行的做法应该是这样子
看, 一样的实现了要求,代码却简洁了许多。如果把代码的实现方式和我们平时的穿着来做对比, 这种实现方式就像是走时尚潮流尖端的穿着打扮,比如说电视里走在t台上的模特的穿着,因为这是es6的语法,由于要兼容老式浏览器的缘故,很多程序员不敢明目张胆的使用。
而前一种方法就像是上世纪的中山装,你穿出去没问题,但肯定会被人家说是土鳖。
更一般的符合大众审美的写法是这样子的
这种写法和第一种写法思路是相同的, 不同点在于,第一种方法使用的是lamda表达式,而这种方法使用的是匿名函数。
事实上,匿名函数在功能上和lambda表达式是没有差别的,只是叫法不一样,此外,lambda表达式写法更加简洁一些。
在javascript中,lamda表达式可以这样写
()=>{}
而匿名函数要这样写
function(){return;}
lambda表达式相对于匿名函数可以省略function和return两个关键字。
lambda的原理就是把函数当做另一个函数的参数来使用,以及不用声明这个函数,使用的时候可以直接写。
这一点我们的老前辈c语言和c++11之前的c++就做不到,在这两位前辈的世界里,要把函数当做参数传递需要使用函数指针, 使用前要先声明函数
test函数接受一个函数类型参数,callback函数就被作为这个参数传递。 这种写法没什么不好的,就是不够飘逸,就像金庸小说里的武功,这写法如同少林寺的七十二绝技,威力巨大, 却朴实无华,没有如凌波微步、北冥神功、天三六阳掌、天山折梅手这些武功那般吸引观众的眼球。
然而, 我们不能怪c和c++不够华丽, 毕竟这两门语言是上古时期的语言,是现在主流计算机语言们的祖宗, 从那个时代的角度去看待这样语言特性,已经是非常先进了。
就连之后的后起之秀java也没有做到这样好, java发展出了另一种丧心病狂的模式。 java8之前没有函数指针,没有匿名函数,更加没有lambda表达式。 在java中要实现这种编程模式只能使用类,可以是具名类, 也可以是匿名类, 在java的世界里,函数不能独立存在,它必须依赖于类。
于是,要把一个函数当参数传递, 只能传递一个类实例,这个类中再带上这个函数。
代码像这个样子
或者这样
原本几行代码可以搞定的事情却被写成了十几行,而且全是毫无意义的仪式性代码。怪不得人家常说java是用来写大型软件的,尼玛,几行代码硬生生被写成了几十行,这种写法能不大型吗
后来的java8支持lambda表达式,改善了这个问题,使java代码简洁了不少,但是那已经是java的第一个版本发布20年以后的事情了, 在这二十年里,不知道让多少java程序员写了多少无用的代码, 做了多少无用功。 但是谁叫它牛逼呢, 常年占据20%的编程语言份额, 死皮赖脸不知上进也没什么,吃老本都饿不死了。 看看人家c#, 够上进吧, 还不是连自己的腰都摸不到。
说到这里,不得不提一下我们亲爱的世界上最好的语言php,php有匿名函数,但是这个匿名函数算不算lambda表达式呢?从广义的角度去理解,应该算,因为匿名函数和lambda表达式能实现同样的功能。从狭义的角度理解,因该不算,lambda表达式讲究的是飘逸潇洒,匿名函数太臃肿了,如果它自认是lambda表达式, 我都替他不好意思。
php中的lambda表达式是这样写的
function test($callback) {
$callback();
}
function main() {
$data = [1,2,3,4,5];
test(function() use($data){
//dosomething
})
}
main函数调用test函数传递的就是匿名函数(lambda表达式),这种写法和老式的javascript一样,虽然不优雅,但也挺和谐的。
且慢,这个匿名函数为什么带一个use关键字, 这个use关键字是什么鬼?
话说php的匿名函数带个use关键字这事吧, 我觉得有好有坏。 php的匿名函数默认是无法访问匿名函数自身作用域除this关键字引用的类实例以外的变量的,从上面的示例来说, 如果不使用use关键字,匿名函数中的代码将无法访问$data变量。 use关键字的作用就是导入这个变量,使匿名函数可以访问它。 所以, 使用不方便,就是use关键字的坏处, 函数用个变量, 还要特定的关键字导入, 坑了个爹。
然而,凡事要看两面,使用use关键字也能带来好处。用了use关键字,我们一眼就能看出这个匿名函数用了哪些外部变量,这对代码的可维护性起到一定的正面作用。不过就我个人来讲,还是非常讨厌这个关键字的,我要的是方便,可维护性什么的, 一边玩去。哥揍是这么任性。
最后呢,我们聊一聊lambda表达式的集大成者, kotlin。这门语言想必认识的人不多,用的人更少,不过它亲爹做的产品程序员们是家喻户晓的, 如intellij idea、phpstorm、webstorm这些知名IDE都是, 这可都是除visual studio以外最好的集成开发环境。至于它的干爹,想必知道的人更多,google,成立不到二十年,市值超过微软,智能手机系统安卓就是他家的,可惜他家的拳头产品google搜索引擎在我们天朝无法使用。
kotlin的lambda表达式可以这样写
{}
就一个花括号,连常规的lambda表达式的括号和箭头都省了。 上面那个臃肿的java匿名类,换成kotlin就是这样子
protected void onCreate(Bundle savedInstanceState) {
btn.setOnClickListener({
//dosomething
});
}
代码量瞬间减少了90%
有的同学要问了,这个lambda表达式如何接受参数
你可以这样
protected void onCreate(Bundle savedInstanceState) {
btn.setOnClickListener({ item ->
//dosomething
});
}
这个箭头, 不用的时候可以省略,用的时候可以带上,多么人性化。
综上所述,论lambda表达式的易用性,kotlin排第二, 就没语言敢排第一。 另外,程序员在编程的时候, 一定要多用lambda,因为这是一种提高生产力的有力工具, 毕竟现在是二十一世纪了,要是再写上世纪80年代的代码,我都替他感到丢人。
- 为自定义配置的编辑提供”智能感知”的支持
- 在ASP.NET Core应用中如何设置和获取与执行环境相关的信息?
- 在ASP.NET MVC中如何应用多个相同类型的ValidationAttribute?
- [ASP.NET MVC]如何定制Numeric属性/字段验证消息
- 为.NET Core项目定义Item Template
- 晚绑定场景下对象属性赋值和取值可以不需要PropertyInfo
- 一个关于反序列化的小问题
- 两个简单的扩展方法:TrimPrefix和TrimSuffix
- 谈谈Nullable<T>的类型转换问题
- ASP.NET MVC是如何运行的(3): Controller的激活
- ASP.NET MVC是如何运行的[2]: URL路由
- 一个简单的小程序演示Unity的三种依赖注入方式
- 在Entity Framework中使用存储过程(三):逻辑删除的实现与自增长列值返回
- 在Entity Framework中使用存储过程(四):如何为Delete存储过程参数赋上Current值?
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Java8 Stream流的终端操作
- Python 爬取王者农药全套皮肤
- 时间都去哪儿了--python性能优化
- Python干货 | 遥感影像拼接
- Java8 Stream 创建流
- Java8 Stream 基本类型特化流
- Java8 Stream 自定义收集器Collector
- 收藏|Flink比Spark好在哪?
- SpringCloud Config 分布式配置
- 经过一年的煎熬,我们还是决定把系统升级成基于 Spring Cloud 的微服务架构
- OpenCV:人脸检测。
- 如何设计缓存系统:缓存穿透,缓存击穿,缓存雪崩解决方案分析
- OpenCV:图像检索。
- Zuul路由网关
- OpenCV:模板匹配。