Go에서의 간단한 함수형 프로그래밍 구현.
제네릭을 이용하기 때문에 1.18 이상의 버전이 필요하다.
타겟(배열, 슬라이스, 오브젝트 등)을 Shell
이라는 단위로 감싼 뒤 그 객체를 여러 함수들을 이용해서 다룬다.
모든 fp 함수들은 *Shell
타입 파라미터를 받으며 F
라는 함수를 이용해서 여러 함수들을 연결하여 함수형 프로그래밍을 진행한다.
함수형 프로그래밍을 좀 더 쉽게 가능케 해주는 여러 타입들이 있다.
// 파이프라인을 이루기 위한 함수
type F func(*Shell) *Shell
// 1개의 제네릭 타입을 받는 함수
type P1[P, R any] func(P) R
// 2개의 제네릭 타입을 받는 함수
type P2[P1, P2, R any] func(P1, P2) R
// 1개의 제네릭 타입 및 인덱스를 받는 함수
type Pi1[P, R any] func(int, P) R
// 2개의 제네릭 타입 및 인덱스를 받는 함수
type Pi2[P1, P2, R any] func(int, P1, P2) R
// 2개의 제네릭 타입 및 인덱스를 받는 void형 함수
type Pi2V[P1, P2 any] func(int, P1, P2)
type A func(any)
자바스크립트와 좀 유사한 면이 있다.
Map[T, U any](convert Pi1[*T, *U]) F
Filter[T any](f Pi1[*T, bool]) F
Slice[T any](idxes ...int) F
Reduce[T, U any](reducer Pi2[*T, *U, *U]) F
Sort[T any](sorter P2[*T, *T, bool]) F
ArrayCopy[T any]() F
Func[T, U any](f P1[T, U]) F
Some[T any](f Pi1[*T, bool]) F
Every[T any](f Pi1[*T, bool]) F
ForEach[T any](f Pi2V[*T, []T]) F
Reverse[T any]() F
Append[T any](elements []T) F
MapOne[T, U any](f P1[*T, *U]) F
함수들을 연결하는 방법은 2가지가 있다.
Pipe
를 이용해서 F
들을 연결할 수 있다.
// `I`는 인풋, `O`는 아웃풋을 의미한다.
Pipe[I, O any](input I, funcs ...F) O
// 순서를 역정렬한 뒤 문자열로 바꾸고 싶다면,
stringArray := fpgo.Pipe[[]int, []string](
[]int{1, 2, 3},
fpgo.Reverse[int](),
fpgo.Map[int, string](func(idx int, element *int) *string) {
s := fmt.Sprintf("No.%d", *element)
return &s
}
)
fmt.Println(stringArray) // [No.3 No.2 No.1]
ProcessingPipe
를 통해 전/후처리를 할 수 있다.
// processors 배열의 형태: {preprocessor, postprocessor}
ProcessingPipe[I, O any](input I, processors [2]A, funcs ...F) O
// 전/후를 확인하고 싶다면,
fpgo.ProcessingPipe[[]int, []int](
[]int{1, 2, 3},
[2]fpgo.A{
func(a any) {
fmt.Printf("before: %v\n", a)
},
func(a any) {
fmt.Printf("after: %v\n", a)
},
},
functions...,
)
위의 Pipe
예시를 체이닝을 통해 구현한 모습은 아래와 같다.
stringArray := fpgo.New([]int{1, 2, 3}).
F(fpgo.Reverse[int]()).
F(fpgo.Map[int, string](func(idx int, element *int) *string) {
s := fmt.Sprintf("No.%d", *element)
return &s
}).V.([]string)
fmt.Println(stringArray) // [No.3 No.2 No.1]
go get github.com/p9595jh/fpgo
import "github.com/p9595jh/fpgo"