• 谈谈高阶函数给我们带来了什么。


    什么是高阶函数

    一句话解释的话,就是函数可以作为参数以变量的方式持有,引用,构造和使用
    一些文章我随手搜的,大家可以看看,它本身的概念并不复杂。
    高阶函数-廖雪峰
    高阶函数-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角度来看,根本就是花大力气用密码手段写了一份说明性文档而已。

  • 相关阅读:
    重载小于号
    无聊的会议
    程序内存和时间
    对拍
    读入和输出优化
    codevs 3269 混合背包
    清北第三套题
    codevs 2188 最长上升子序列
    清北第二套题
    [COGS896] 圈奶牛
  • 原文地址:https://www.cnblogs.com/suijing/p/7121734.html
Copyright © 2020-2023  润新知