Go的几种函数式编程范例?

函数一等公民,在Go中兼顾了函数式编程所以可以将func作为参数和返回值随意操作

import "fmt"

func main() {
    var list = []string{"Orange", "Apple", "Banana", "Grape"}
    var out = mapForEach(list, func(it string) int {
        return len(it)
    })
    fmt.Println(out)
}

func mapForEach(arr []string, fn func(it string) int) []int {
    var newArray = []int{}
    for _, it := range arr {
        newArray = append(newArray, fn(it))
    }
    return newArray
}

柯里化

package main

func main() {
    var add1 = add(1)
    println(add1(2))
}

func add(x int) func(y int) int {
    return func(y int) int {
        return x + y
    }
}

值得注意的一点是函数式编程本质就是:stateless和immutable,即使我们可以操作改变外部数据我们也不要做这样的尝试,因为它已经违背了原则。

stateless:函数不维护任何状态。函数式编程的核心精神是 stateless,简而言之就是它不能存在状态,打个比方,你给我数据我处理完扔出来。里面的数据是不变的。

immutable:输入数据是不能动的,动了输入数据就有危险,所以要返回新的数据集。

错误的尝试

var holder = map[string]int{}

func sum(a, b int) int {
    c := a + b
    holder[fmt.Sprintf("%d+%d", a, b)] = c
    return c
}

一般递归

func factorial(num int) int {
    if num == 0 {
        return 1
    } else {
        return num * factorial(num - 1)
    }
}

这种递归为什么不太好,因为我们的num在前半部递归树实际上是一直不变的,也就是说我们一直引用着前面的空间,这样容易出现溢出。

尾递归

func factorial(accumulator, num int) int {
    if num == 0 {
        return accumulator
    } else {
        return factorial(accumulator * num, num - 1)
    }
}

func factorialTailRec(num int) int {
    return factorial(1, num)
}

实际上就是每次将上次的结果传下去,这样就相当于每次再call一个func

lazy模式

func add(x int) int {
    fmt.Println("executing add")
    return x + x
}

func multiply(x int) int {
    fmt.Println("executing multiply")
    return x * x
}

func main() {
    fmt.Println(addOrMultiply(true, add, multiply, 4))
    fmt.Println(addOrMultiply(false, add, multiply, 4))
}

// This is now a higher-order-function hence evaluation of the functions are delayed in if-else
func addOrMultiply(add bool, onAdd, onMultiply func(t int) int, t int) int {
    if add {
        return onAdd(t)
    }
    return onMultiply(t)
}

这样就可以避免性多调用一次add或者mutiply