Skip to content

Instantly share code, notes, and snippets.

@i
Created September 7, 2017 22:20
Show Gist options
  • Save i/bd7875ab3239513b04e00ca5d7f38ac1 to your computer and use it in GitHub Desktop.
Save i/bd7875ab3239513b04e00ca5d7f38ac1 to your computer and use it in GitHub Desktop.
package main
import (
"errors"
"fmt"
"reflect"
)
func pipe(fns []interface{}, args ...interface{}) (interface{}, error) {
for i := range fns {
t1 := reflect.TypeOf(fns[i])
if t1.Kind() != reflect.Func {
return nil, fmt.Errorf("invalid type at fns[%d]: %v", i, t1.Kind())
}
if i > 0 {
t2 := reflect.TypeOf(fns[i-1])
if t1.NumIn() != t2.NumOut()-1 {
panic("bad")
}
for j := 0; j < t1.NumIn(); j++ {
if t1.In(j) != t2.Out(j) {
panic("bad")
}
}
} else {
if len(args) != t1.NumIn() {
panic("bad")
}
}
}
input := make([]reflect.Value, 0, len(args))
for _, arg := range args {
input = append(input, reflect.ValueOf(arg))
}
for i := range fns {
fn := reflect.ValueOf(fns[i])
fmt.Println(i, input)
input = fn.Call(input)
if !checkNil(input[len(input)-1]) {
return nil, fmt.Errorf("got error running command: %v", input[len(input)-1])
}
input = input[:len(input)-1]
}
return input[0], nil
}
func checkNil(v reflect.Value) (b bool) {
defer func() {
if r := recover(); r != nil {
b = false
}
}()
return v.IsNil()
}
func main() {
v, err := pipe([]interface{}{
func(i int) (float64, error) { return 4.0, nil },
func(f float64) (float64, error) { return f + 1, nil },
func(f float64) (float64, error) { return 0, errors.New("failure") },
func(f float64) (float64, error) { return f + 1, nil },
}, 5)
fmt.Println(v, err)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment