Pkg.go.dev is a new destination for Go discovery & docs. Check it out at pkg.go.dev/github.com/Fliko/cardinal and share your feedback.

package cardinal

import "github.com/Fliko/cardinal"

Package cardinal is a Promise library written in Go using the reflect package.

Before getting started there a few basic rules you need to understand:

1. To reject a promise return a non-nil error 2. Nil errors will not be piped into the next chained function

cardinal.go cardinal_functions.go

❖ type PromiseStruct struct { Status stat // Describes the success of the previously ran promise Result []reflect.Value // Holds the function output arguments of the previously ran promise Order int // For promise methods that return multiple promises, this is used to keep their return arguments in order }

PromiseStruct holds the data for running the Promise

Example should type check and throw a sensible error Code: stuff := Promise(func() int { return 3 }). Then(func(x int) (int, error) { fmt.Println(x) return x * x, nil }). Then(func(x float64) (float64, error) { fmt.Println(x) return x * x, nil }). Catch(func(e error) error { fmt.Println(e) return e }) fmt.Println(stuff.Result[0]) Output: 3 Args should be float64 but got int Args should be float64 but got int

Promise is a generator for the PromiseStruct and it only accepts functions with no input arguments

Example should be able to chain then functions piping the values from one to the other Code: stuff := Promise(func() int { return 3 }). Then(func(x int) int { fmt.Println(x) return x * x }). Then(func(x int) { fmt.Println(x) }) fmt.Println(stuff.Result) Output: 3 9 []

All takes several functions and runs them in parallel The next chaining function will need to take the input of all function returns in order

Example should type check and throw a sensible error Code: stuff := Promise(func() int { return 3 }). All( func(x int) (int, error) { fmt.Println(x) time.Sleep(50 * time.Millisecond) //Guarantee Order return x + 3, nil }, func(x int) (int, error) { fmt.Println(x) return x * x, nil }) fmt.Println(stuff.Result[0]) fmt.Println(stuff.Result[1]) Output: 3 3 6 9 Example (Then) should properly pass the result of All to a Then Code: stuff := Promise(func() int { return 3 }). All( func(x int) (int, error) { fmt.Println(x) return x * x, nil }, func(x int) (int, error) { fmt.Println(x) return x * x, nil }). Then(func(x int, y int) int { fmt.Println(x, y) return x * y }) fmt.Println(stuff.Result[0]) Output: 3 3 9 9 81

Catch runs a given function if any promise before it failed to complete successfully

Example should skip Then and run Catch if error returned is not nil Code: stuff := Promise(func() int { return 3 }). Then(func(x int) (int, error) { fmt.Println(x) return x * x, errors.New("should show up in Catch") }). Then(func(x int) (int, error) { fmt.Println(x) return x * x, nil }). Catch(func(e error) error { fmt.Println(e) return e }) fmt.Println(stuff.Result[0]) Output: 3 should show up in Catch should show up in Catch

❖ func (p PromiseStruct) Map(s interface{}, fn interface{}) PromiseStruct

Map takes an array and applies a given function to each element in the array The return of Map is similar to All, the next chained method will need to handle all passed returns in order

Example Should map a given array with a given function Code: fruits := []string{"apples", "bananas", "oranges", "cherries"} stuff := Promise(func() {}). Map(fruits, func(s string) string { return s + " are not a fruit" }). Then(func(a string, b string, c string, d string) string { fmt.Println(a) return b + " and " + d }) fmt.Println(stuff.Result[0]) Output: apples are not a fruit bananas are not a fruit and cherries are not a fruit

❖ func (p PromiseStruct) Reduce(s interface{}, fn interface{}, init interface{}) PromiseStruct

Reduce takes a slice and give a function and initial value creates a single value

Example should reduce a given array with a given function Code: fruits := []string{"apples", "bananas", "oranges", "cherries"} stuff := Promise(func() {}). Reduce(fruits, func(a string, b string, i int, l int) string { return a + " " + b }, nil). Then(func(s string) string { fmt.Println(s) return s }) fmt.Println(stuff.Result[0]) Output: apples bananas oranges cherries apples bananas oranges cherries

Then runs a given function with the piped in parameters as long as the previous promise was successful

Example should not skip Then and not run Catch if error returned is nil Code: stuff := Promise(func() int { return 3 }). Then(func(x int) (int, error) { fmt.Println(x) return x * x, nil }). Then(func(x int) (int, error) { fmt.Println(x) return x * x, nil }) fmt.Println(stuff.Result[0]) Output: 3 9 81

ThenMap is like Map but takes the array from the previously executed promise

Example should map a piped array with a given function Code: fruits := []string{"apples", "bananas", "oranges", "cherries"} stuff := Promise(func() []string { return fruits }). Map(fruits, func(s string) string { return s + " are not a fruit" }). Then(func(a string, b string, c string, d string) string { fmt.Println(a) return b + " and " + d }) fmt.Println(stuff.Result[0]) Output: apples are not a fruit bananas are not a fruit and cherries are not a fruit

❖ func (p PromiseStruct) ThenReduce(fn interface{}, init interface{}) PromiseStruct

ThenReduce is like Reduce but the slice comes from a previous promise

Example Code: fruits := []string{"apples", "bananas", "oranges", "cherries"} stuff := Promise(func() []string { return fruits }). ThenReduce(func(a string, b string, i int, l int) string { return a + " " + b }, "grapes") fmt.Println(stuff.Result[0]) Output: grapes apples bananas oranges cherries