go functional是一个go软件包,提供功能性编程功能。
什么是功能编程?
功能编程是一种样式,最著名的是LISP,Haskell,F#,Clojure和Erlang使用的样式,该样式(在不同程度上)提供了以下特征:
- 功能处理大多数逻辑
- 功能是纯粹的。函数唯一知道的是传递的内容。它不能突变其输入。它只能产生新的输出。
- 功能是一流的公民。它们可以作为参数传递到其他功能。
- 功能可以束缚。一个函数的输出可以是另一个函数的输入。在链条结束时,您将获得所需的数据。
这是一种极其表现力的风格,使阅读代码变得高兴。
它是什么样子的?
official docs上有很多示例,但简而言之,可以使用这样的功能:
import (
"github.com/sean9999/GoFunctional/fslice"
)
// apply a filter function and then a map function to get squares of primes
inputNums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
outputNums := fslice.From(inputNums).Filter(func(v int, _ int, _ []int) bool {
return primes.IsPrime(v)
}).Map(func(v int, _ int, _ []int) int {
return v * v
})
fmt.Println(outputNums)
// Output: [4 9 25 49 121]
在上面,我们拿起一片整数,过滤所有不是素数的,剩余的,然后返回。我们将用户定义的功能直接作为匿名函数传递到fslice.Map和fslice.Filter中,但这可以很容易地进行。
onlyPrimes := func(val int, _ int, _ []int) {
return primes.IsPrime(val)
}
square := func() {
return val * val
}
outputNums := fslice.From(inputNums).Filter(onlyPrimes).Map(square)
fmt.Println(outputNums)
// Output: [4 9 25 49 121]
以上可能被认为比上一个更可读。它们在功能上是等等的。
FSLICE采用的一般模式是:
- 每种Fslice方法都采用user-defined function
- 用户定义的功能通常采用三个参数:值,索引和基础切片的整体。
- 用户定义的函数用于切片中的每个元素,或者尽可能多次(如果可以提早退出,它将)。
因此,例如,Fslice.Map()采用匹配签名MapFunction的用户定义功能。用户定义的功能采用一个值,并产生同一类型的另一个值。由于fslice.map()调用该切片的每个元素的功能,因此返回值是另一个切片。
通常,您只需要在用户定义的函数中的值,但是有时您需要完整的参数。这是FSLICE方法提早返回的示例,因为它具有所需的所有信息,并使用了所有三个参数:
import (
"github.com/fxtlabs/primes"
"github.com/sean9999/GoFunctional/fslice"
)
// are any two sequential integers co-prime?
inputSlice := []int{1,2,3,4,5,6,7,8,9,20,24,665,771}
isCoPrimeWithPrevious := func(n int, i int, arr []int) bool {
if n > 0 {
m := arr[i-1]
return primes.Coprime(m, n)
}
return false
}
answer := fslice.From(inputSlice).Some(isCoPrimeWithPrevious)
fmt.Println(answer)
// Output: true
一组方法及其签名受到Javascript spec for iterative methods on arrays的启发。 JavaScript中的一些数组方法可突变基础阵列。进行功能可以避免这些。它的目标是更尊重功能编程原则。
下一步是什么?
除了JavaScript之外,我想找到一套半授权的方法,以基于工作。
我想以与fslice相同的方式开发FMAP。
我想通过介绍Functor的概念来找到一种提供更大多态性的方法。这可以使开发人员一次仅限于一种类型(int,float64,string等)。
拉力请求受到热情欢迎。