Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Monad, Functional Programming features for Golang

License

NotificationsYou must be signed in to change notification settings

TeaEntityLab/fpGo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

tagGo Report CardcodecovTravis CI Build StatusGoDoc

licensestarsforks

Monad, Functional Programming features for Golang

Active Branches:

ForGenerics version(>=go1.18):generics

go get github.com/TeaEntityLab/fpGo/v2

ForNonGenerics version(<=go1.17):non-generics

go get github.com/TeaEntityLab/fpGo

Why

I love functional programing, Rx-style coding, and Optional usages.

However it's hard to implement them in Golang, and there're few libraries to achieve parts of them.

Thus I implemented fpGo. I hope you would like it :)

Features

  • Optional/Maybe

  • Monad, Rx-like

  • Publisher

  • Pattern matching

  • Fp functions

  • Java8Stream-like Collection

  • Queue (LinkedListQueue/ChannelQueue/BufferedChannelQueue/ConcurrentQueue)

  • PythonicGenerator-like Coroutine(yield/yieldFrom)

  • Akka/Erlang-like Actor model(send/receive/spawn/states)

  • network/SimpleHTTP inspired byRetrofit

  • worker/WorkerPool inspired by JavaExecutorService & goroutine pool libs

Special thanks

Usage

Optional (IsPresent/IsNil, Or, Let)

varmMaybeDef[interface{}]varorValintvarboolValbool// IsPresent(), IsNil()m=Maybe.Just(1)boolVal=m.IsPresent()// trueboolVal=m.IsNil()// falsem=Maybe.Just(nil)boolVal=m.IsPresent()// falseboolVal=m.IsNil()// true// Or()m=Maybe.Just(1)fmt.Println((m.Or(3)))// 1m=Maybe.Just(nil)fmt.Println((m.Or(3)))// 3// Let()varletValintletVal=1m=Maybe.Just(1)m.Let(func() {letVal=2})fmt.Println(letVal)// letVal would be 2letVal=1m=Maybe.Just(nil)m.Let(func() {letVal=3})fmt.Println(letVal)// letVal would be still 1

MonadIO (RxObserver-like)

Example:

varm*MonadIODef[interface{}]varactualIntintm=MonadIO.Just(1)actualInt=0m.Subscribe(Subscription[interface{}]{OnNext:func(ininterface{}) {actualInt,_=Maybe.Just(in).ToInt()  },})fmt.Println(actualInt)// actualInt would be 1m=MonadIO.Just(1).FlatMap(func(ininterface{})*MonadIODef[interface{}] {v,_:=Maybe.Just(in).ToInt()returnMonadIO.Just(v+1)})actualInt=0m.Subscribe(Subscription[interface{}]{OnNext:func(ininterface{}) {actualInt,_=Maybe.Just(in).ToInt()  },})fmt.Println(actualInt)// actualInt would be 2

Stream (inspired by Collection libs)

Example(Generics):

vars*StreamDef[int]vartempString=""s=StreamFromArray([]int{}).Append(1,1).Extend(StreamFromArray([]int{2,3,4}))tempString=""for_,v:=ranges.ToArray() {tempString+=Maybe.Just(v).ToMaybe().ToString()}fmt.Println(tempString)// tempString would be "11234"s=s.Distinct()tempString=""for_,v:=ranges.ToArray() {tempString+=Maybe.Just(v).ToMaybe().ToString()}fmt.Println(tempString)// tempString would be "1234"

Example(Non-Generics/interface{}):

vars*StreamForInterfaceDefvartempStringstrings=StreamForInterface.FromArrayInt([]int{}).Append(1,1).Extend(StreamForInterface.FromArrayInt([]int{2,3,4})).Extend(StreamForInterface.FromArray([]interface{}{nil})).Extend(nil)tempString=""for_,v:=ranges.ToArray() {tempString+=Maybe.Just(v).ToMaybe().ToString()}fmt.Println(tempString)// tempString would be "11234<nil>"s=s.Distinct()tempString=""for_,v:=ranges.ToArray() {tempString+=Maybe.Just(v).ToMaybe().ToString()}fmt.Println(tempString)// tempString would be "1234<nil>"s=s.FilterNotNil()tempString=""for_,v:=ranges.ToArray() {tempString+=Maybe.Just(v).ToMaybe().ToString()}fmt.Println(tempString)// tempString would be "1234"

Queue(LinkedListQueue/ChannelQueue/BufferedChannelQueue/ConcurrentQueue) (inspired by Collection libs)

LinkedListQueue(Shift/Unshift/Push/Pop), ConcurrentQueue(inspired by Java)

Example:

varqueueQueue[int]varstackStack[int]varerrerrorvarresultintlinkedListQueue:=NewLinkedListQueue[int]()queue=linkedListQueuestack=linkedListQueueconcurrentQueue:=NewConcurrentQueue[int](queue)// As a Queue, Put(val) in the TAIL and Take() in the HEADerr=queue.Offer(1)err=queue.Offer(2)err=queue.Offer(3)result,err=queue.Poll()// Result should be 1result,err=queue.Poll()// Result should be 2result,err=queue.Poll()// Result should be 3result,err=queue.Poll()// Err: ErrQueueIsEmpty// As a Stack, Push(val) & Pop() in the TAIL.err=stack.Push(1)err=stack.Push(2)err=stack.Push(3)result,err=stack.Pop()// Result should be 3result,err=stack.Pop()// Result should be 2result,err=stack.Pop()// Result should be 1result,err=stack.Pop()// Err: ErrStackIsEmpty

BufferedChannelQueue(Offer/Take/TakeWithTimeout)

Example:

varerrerrorvarresultintvartimeout time.DurationbufferedChannelQueue:=NewBufferedChannelQueue[int](3,10000,100).SetLoadFromPoolDuration(time.Millisecond/10).SetFreeNodeHookPoolIntervalDuration(1*time.Millisecond)err=queue.Offer(1)err=queue.Offer(2)err=queue.Offer(3)timeout=1*time.Millisecondresult,err=bufferedChannelQueue.TakeWithTimeout(timeout)// Result should be 1result,err=bufferedChannelQueue.TakeWithTimeout(timeout)// Result should be 2result,err=bufferedChannelQueue.TakeWithTimeout(timeout)// Result should be 3

Actor (inspired by Akka/Erlang)

Actor common(send/receive/spawn/states)

Example:

actual:=0// Channel for resultsresultChannel:=make(chaninterface{},1)// Message CMDscmdSpawn:="spawn"cmdShutdown:="shutdown"// TesteeactorRoot:=Actor.New(func(self*ActorDef[interface{}],inputinterface{}) {// SPAWN: for ROOTifinput==cmdSpawn {self.Spawn(func(self*ActorDef[interface{}],inputinterface{}) {// SHUTDOWN: for Childrenifinput==cmdShutdown {self.Close()return      }// INT cases: Childrenval,_:=Maybe.Just(input).ToInt()resultChannel<-val*10    })return  }// SHUTDOWN: for ROOTifinput==cmdShutdown {for_,child:=rangeself.children {child.Send(cmdShutdown)    }self.Close()close(resultChannel)return  }// INT cases: ROOTintVal,_:=Maybe.Just(input).ToInt()ifintVal>0 {for_,child:=rangeself.children {child.Send(intVal)    }  }})// Sequential Send messages(async)gofunc() {actorRoot.Send(cmdSpawn)actorRoot.Send(10)actorRoot.Send(cmdSpawn)actorRoot.Send(20)actorRoot.Send(cmdSpawn)actorRoot.Send(30)}()i:=0forval:=rangeresultChannel {intVal,_:=Maybe.Just(val).ToInt()actual+=intVali++ifi==5 {goactorRoot.Send(cmdShutdown)  }}// Result would be 1400 (=10*10+20*10+20*10+30*10+30*10+30*10)fmt.Println(actual)

Actor Ask (inspired by Akka/Erlang)

actorRoot:=Actor.New(func(self*ActorDef[interface{}],inputinterface{}) {// Ask cases: ROOTswitchval:=input.(type) {case*AskDef[interface{},int]:intVal,_:=Maybe.Just(val.Message).ToInt()// NOTE If negative, hanging for testing Ask.timeoutifintVal<0 {break        }val.Reply(intVal*10)break    }})// var timer *time.Timervartimeout time.Durationtimeout=10*time.Millisecond// Normal cases// Result would be 10actual=AskNewGenerics[interface{},int](1).AskOnce(actorRoot)// Ask with Timeout// Result would be 20actual,_=AskNewGenerics[interface{},int](2).AskOnceWithTimeout(actorRoot,timeout)// Ask channel// Result would be 30ch:=AskNewGenerics[interface{},int](3).AskChannel(actorRoot)actual=<-chclose(ch)// Timeout cases// Result would be 0 (zero value, timeout)actual,err=AskNewGenerics[interface{},int](-1).AskOnceWithTimeout(actorRoot,timeout)

Compose

Example:

varfn01=func(args...int) []int {val:=args[0]returnSliceOf(val+1)}varfn02=func(args...int) []int {val:=args[0]returnSliceOf(val+2)}varfn03=func(args...int) []int {val:=args[0]returnSliceOf(val+3)}// Result would be 6result:=Compose(fn01,fn02,fn03)((0))[0]

[8]ページ先頭

©2009-2025 Movatter.jp