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

上一篇中集中展示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 函数编程及函数式编程)