什么是高阶函数

一句话解释的话,就是函数可以作为参数以变量的方式持有,引用,构造和使用
一些文章我随手搜的,大家可以看看,它本身的概念并不复杂。
高阶函数-廖雪峰
高阶函数-wiki
其实现在主流语言差不多都支持了,之前的java7利用接口其实也算支持,c#的委托,js更不用说,写了回调就算。
所以我这里主要是谈谈他对编程思维的影响。

基本讲解

让我们先从kotlin的一个官方库函数的实现开始讲起,这个函数只有一行代码

/**
 * Calls the specified function [block] with `this` value as its receiver and returns `this` value.
 */
@kotlin.internal.InlineOnly
public inline fun <T> T.apply(block: T.() -> Unit): T { block(); return this }

apply是接收一个针对T类型的扩展方法的lambda形式(Ps:kt可以将扩展方法以lambda传递,这是它相比C#的一个重要改进)
后面的block(),其实是this.block()的简写(Ps:kt在扩展lambda中,可以省略this这个调用上下文)
表意为,以T作为this,调用一下针对T的(lambda形式)扩展函数,这个lambda可以对T做一些事情,做完了这个函数仍然是返回T.

这个解释可能不太直观,我们继续上代码:(Ps:kt实例化对象时候,调用构造方法即为实例化,不需要使用new关键字)

Ps:这个示例,功能类似于C#的实例化对象时候的属性构造,但意思是完全不同的,后面是一个lambda语句,是可以定义变量,执行语句的。
我们把这个场景分析一下:new一个实例出来,并给他赋一些初始值,然后调用它做一些事情

前两者其实是紧密联系在一起的"原子性逻辑",如果是java,你不得不把这个场景分成三段:

1 new 2 赋值 3 使用

如果是java,我们可能经常见到
1.MyDto dto = new MyDto() ; 紧跟着就是二三十行的赋值代码,需要的值有时候可能还需要通过计算得到,重构吧,又得传一大推参数。

但如果是kotlin使用了apply,那么就成了这样

1 (new, 赋值) 2 使用

注意我的折叠,我一共折叠了十多行的赋值代码,这样阅读起来,new和赋值就是一个整体,
同时如果我在apply中定义的一些临时变量,会被锁在这个作用域里面,不会污染到外部,也减少了阅读代码的成本.
同时这个lambda闭包中,也能访问到之前定义的一些变量

再看这个,如果不使用apply,我们的链式构造queryDSL就会被if else逻辑截断,但如果我们用了apply,就可以在合适的地方插入这段逻辑,而又保持condition的链式流转

其实加了inline后,这些代码最终生成出来的东西,和java其实是一样的,但是它能在语法级别,帮你组织你的代码和逻辑,这样你写出来的Kotlin代码就是立体的,而且给人一种有组织有纪律的感觉,不想java一条线撸下来.

如果对高阶函数有一点理解的,会知道这真的是非常简单的语法,在很多fp语言里面更是早就被用烂了的东西.

不过很多被oo洗脑多年的,无法意识到它带来的价值.

比如我们学的一些设计模式,什么策略模式,装饰模式等等,用起来别扭,写起来累人,但一旦我们打开了这扇思维的门,我们发现,原来这些是可以组装,传递的,根本就用不着oo那套奇技淫巧。

方法不再是我们逻辑的最小单元,函数可以作为参数,互相传递,组装,这可以让我们可以用另一种思维去组织我们的代码。

还有工厂模式,有些情况确实是需要一个集中管理比如DI,
但大多数时候,我们从duck type角度来看,根本就是花大力气用密码手段写了一份说明性文档而已。

posted @ 2017-07-05 15:38 碎景 阅读(2054) 评论(1) 推荐(0) 编辑
摘要: 前言 这是我之前在知乎上的一些回答的汇总,感觉还是博客园写这些东西方便一点,也算是理下我的一些思路,现将文章整理后,发布在园子里。 为何是kotlin: 很多人对kt没有一个正确的定位,可能大家第一反应是拿它去和scala,groovy比较. 从语法的角度而言,kotlin丰富且严谨到恰到好处的语法 阅读全文
posted @ 2017-07-05 15:08 碎景 阅读(5725) 评论(1) 推荐(4) 编辑
摘要: 尝试kotlin的起因 因为各种原因(版权,人员招聘),公司的技术体系从c 转到了java,我花了大概两周的时间来上手java,发现java的语法还是非常简单的,基本看着代码就知道什么意思.学习java的过程中,大部分时间都花费在了maven配置,理解spring的ioc上面. 学习的一段时间,我对 阅读全文
posted @ 2016-05-28 22:40 碎景 阅读(5475) 评论(0) 推荐(1) 编辑
摘要: 很多时候我们都需要对实体对象进行序列化与反序列化,而ObjectId类型,只能用mongo的驱动以bson格式来序列化,但我们对外的交互,一般是json格式.有两种解决方案: 1.自己写一个json.net的ObjectIdConverter来针对ObjectId,适用于json.net 2... 阅读全文
posted @ 2015-07-14 17:50 碎景 阅读(5600) 评论(0) 推荐(0) 编辑
摘要: WebEssentials 最高支持到update4如果更新到了update5 RC, 则无法直接安装.解决方法是1,下载WebEssentials2013.vsix 文件.2, 安装7zip3,右击vsix文件,在7zip中打开.4,编辑extension.vsixmanifest 修改 ... 阅读全文
posted @ 2015-06-12 15:53 碎景 阅读(1215) 评论(0) 推荐(0) 编辑
摘要: 前言 这篇其实是上两篇的两个主题思想的承接和发散: 我也想少写注释,想用2-4个很清晰的单词去描述函数,但是这个函数好复杂啊,我恨不得写近百字去描述它,要我用几个单词去描述?臣妾实在是做不到啊~ <如何做到少写注释> 我也不想写这么多if else,然后看着那一堆一堆{}{{}{}{{}}}}}}} 阅读全文
posted @ 2014-08-30 15:56 碎景 阅读(14268) 评论(37) 推荐(16) 编辑
摘要: 使用数据实体的好处我这里就不多说了,但大家享受这些好处的时候,难免也对那些琐碎的赋值代码感到厌烦,基于此,我认为掌握一个oom的使用,还是很有必要的. 这种类型的工具有很多,比如automapper,EmitMapper,还有和orm混合的dapper等,各有各的特色, 但综合性能,扩展,易用... 阅读全文
posted @ 2014-07-24 23:43 碎景 阅读(3031) 评论(1) 推荐(1) 编辑
摘要: 最近想学习一门脚本语言,综合考虑,选择了python. 花了几天时间看完了 简明 Python 教程,想着应该写点什么东西才好,刚好我使用的是3.x版本,以前好多2.x的代码都直接报错,尤其是print语句,手动加()太蛋疼,遂起了写个自动加()的脚本的心思. 先是在这里找到了python ... 阅读全文
posted @ 2014-06-13 00:14 碎景 阅读(3451) 评论(0) 推荐(0) 编辑
摘要: 前言: if,相信是童鞋们使用的最频繁的关键字了,而且很多时候,我们使用的if都是在无意识的状态下随手而为。键入if,两下回车(我使用了resharper,可以自动编排if的格式),再信手写下我们需要的逻辑,一段可以“正常运行”的代码就被我们实现了。尽管这段逻辑比较复杂,但在那个时间段,我们对这段业... 阅读全文
posted @ 2014-02-26 21:34 碎景 阅读(4615) 评论(19) 推荐(8) 编辑
摘要: 关于> 这是我新开的一个系列,旨在记录我对整个编码规范,代码风格,语法习惯,架构设计的一些思考,感悟和总结.前言 不知道大家会不会觉得我的标题很噱头,不是一般应该提倡写注释的么?首先我得解释下,我这句话有两个意思! 1,绝非提倡不写注释,而是不要写不必要的注释. 2,命名规范的作... 阅读全文
posted @ 2013-12-29 18:41 碎景 阅读(5301) 评论(26) 推荐(12) 编辑
点击右上角即可分享
微信分享提示