Created
October 5, 2017 16:08
-
-
Save anonymous/a1f016937b2b45ed57af4b42bff47cc3 to your computer and use it in GitHub Desktop.
The worst idea i've ever had
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package chain | |
import ( | |
"fmt" | |
"reflect" | |
) | |
// Chain takes an array of functions, and calls them all, passing the result of the previous call to the next. Any funcs whose last return value is an error have the errors checked and not passed to the next. If an error occurs at any point chain returns with an empty list and the error that happened. | |
// here it is expressed vaguely maths-y which might be clearer. | |
// given a function f[n] which returns a set of values vs: | |
// if the last element of vs is of a type which implements the error type, | |
// the last element is removed from vs and stored as err. | |
// if err is not nil, return an empty slice of values and err. | |
// otherwise, call f[n+1](vs) | |
func Chain(funcs ...interface{}) (res []interface{}, err error) { | |
data := []reflect.Value{} | |
for _, f := range funcs { | |
val := reflect.ValueOf(f) | |
typ := reflect.TypeOf(f) | |
if typ.Kind() != reflect.Func { | |
data = []reflect.Value{} | |
err = fmt.Errorf("one of the funcs wasn't a func.") | |
return | |
} | |
data = val.Call(data) | |
if len(data) > 0 { | |
errVal := data[len(data)-1] | |
if errVal.Type().Implements(reflect.TypeOf((*error)(nil)).Elem()) { | |
errI := errVal.Interface() | |
if errI != nil { | |
err = errI.(error) | |
return | |
} | |
data = data[:len(data)-1] | |
} | |
} | |
} | |
res = make([]interface{}, len(data)) | |
for i, d := range data { | |
res[i] = d.Interface() | |
} | |
return | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package chain_test | |
import ( | |
"fmt" | |
"math" | |
"strconv" | |
) | |
func ExampleChain() { | |
res, err := chain.Chain( | |
func() (string, int) { return "400.2", 32 }, | |
strconv.ParseFloat, | |
math.Ceil, | |
func(f float64) (string, float64) { return "%0.f", f }, | |
fmt.Sprintf, | |
) | |
if err != nil { | |
fmt.Println("there was an error!") | |
} | |
fmt.Println(res[0]) | |
// Output: 401 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
this horror is on me - I've forked it because re-uploading seemed daft.