美文网首页
6. Go 函数编程及函数式编程

6. Go 函数编程及函数式编程

作者: PRE_ZHY | 来源:发表于2018-09-28 01:05 被阅读16次

    上一篇中集中展示Go函数的诸多特性,这一篇将继续理解函数。函数是什么?在Go及多数语言中,它是一段可接受输入,可能有输出的代码块。与编程相比,多数人第一次接触到函数,可能是学习集合,函数,映射等数学知识时,那是的函数,其实是用于描述两个集合之间的映射关系。

    为什么编程中要定义这么一段代码块?因为函数可以减少编程量,通过定义一段代码,在重复利用的时候直接调用,不用再次编写。但在函数编写过程中,又发现定义一大堆成品代码,调用的时候还需要找,所以函数需要名字以区别不同代码;在函数有了名称后,又有人发现,计算一个固定的表达式,如y=kx+b,通常只有x变化,k和b都不变,那么定义的这段代码要有输入值作为参数,同时要返回一个值;再后来,人们发现x可能也不一定是一个数,也可能是一个另外一个表示式,x=at+c。那么最终发现,函数还是作为数学上的函数存在,描述一个事务到另一个事务的映射关系。可能这个映射是名称到一段特殊功能代码的映射,可能是一个变量到另一个变量的映射,更或者是一个函数到另一个函数的映射。

    在此基础上,本篇是想说另一件事情:函数式编程。"函数式编程"是一种"编程范式",也一种程序书写风格与思路。

    函数式编程的风格与思路:

    1. 函数是"第一等公民"(前提条件)

    函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。

    1. 只用"表达式",不用"语句"

    "表达式"(expression)是一个单纯的运算过程,总是有返回值;"语句"(statement)是执行某种操作,没有返回值。函数式编程要求,只使用表达式,不使用语句。也就是说,每一步都是单纯的运算,而且都有返回值。

    1. 没有"副作用"

    指的是函数内部与外部互动(最典型的情况,就是修改全局变量的值),产生运算以外的其他结果。函数式编程强调没有"副作用",意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。

    1. 不修改状态
      函数式编程只是返回新的值,不修改系统变量。因此,不修改变量,也是它的一个重要特点

    2. 引用透明

    引用透明(Referential transparency),指的是函数的运行不依赖于外部变量或"状态",只依赖于输入的参数,任何时候只要参数相同,引用函数所得到的返回值总是相同的。

    在语言层面实现特性以后,函数式编程的关键纯函数的编写,纯函数就是满足后三相风格的函数,只产生结果,不修改状态,且输入输出稳定透明。其直观特征类似于下面的风格,一个函数嵌套另外一个函数,每个函数都有自己的输入输出,就像一个流一样,直到输出结果。

    package main
    
    import (
        "fmt"
    )
    
    func sum(s []int) int {
        result := 0
        for _, v := range s {
            result += v
        }
        return result
    }
    
    func maps(s []int, f func(x int) int) []int {
        sn := make([]int, len(s), cap(s))
        for i, v := range s {
            sn[i] = f(v)
        }
        return sn
    }
    
    func square(x int) int {
            return x * x
        }
    func cube (x int) int {
            return x * x * x
        }
    
    
    func main() {
        fmt.Println(maps([]int{1, 3, 5, 7, 9}, square))
        fmt.Println(sum(maps([]int{1, 3, 5, 7, 9}, cube)))
    }
    /* Result
    [1 9 25 49 81]
    1225
    /*
    

    编写一个好的函数是其实不是一个容易过程,目前为止,遇到的很多问题都非常简单,以至于我们能够非常清晰地界定问题的边界,然后按照不同内容编写不同的函数。但在面对复杂的实际问题时,往往会迷失在杂乱的问题中,这需要不断锤炼,不断的对问题进行抽象,然后就会发现之前写的很多函数由于各种各样的问题需要不断修改。个人的建议有两条:

    1. 在下键盘之前,先下笔将问题搞清楚,规划完成后再开始;
    2. 函数功能要足够的小,函数量不怕多,但函数要精,这样下去写的东西可能才会有更强的生命力。

    Ref:

    1. 函数式编程初探
    2. 函数成了一等公民
    3. Functional Programming HOWTO

    相关文章

      网友评论

          本文标题:6. Go 函数编程及函数式编程

          本文链接:https://www.haomeiwen.com/subject/hyquoftx.html