diff --git a/src/apply/apply.go b/src/apply/apply.go new file mode 100644 index 0000000..85e3590 --- /dev/null +++ b/src/apply/apply.go @@ -0,0 +1,63 @@ +package apply + +import ( + "reflect" +) + +type Type struct { + slice interface{} +} + +// Lift Factory method to encapsulate the type within Type +func Lift(data interface{}) Type { + // check if this is a slice + s := reflect.ValueOf(data) + if s.Kind() != reflect.Slice { + panic("InterfaceSlice() given a non-slice type") + } + return Type{slice: data} +} + +// Map +// panic if map function input and output dont have the same type +// panic if slice type and f input type is not the same type +func (t *Type) Apply(f interface{}) Type { + // make sure that this is a function + v := reflect.ValueOf(f) + if v.Kind() != reflect.Func { + panic("f should be a function") + } + // check the underlying type of the slice + fType := v.Type() + // check function take one parameter of type t and return one out put of the same type + if fType.NumOut() != 1 || fType.NumIn() != 1 { + panic("Function must take one input and produces one output") + } + // get th inbound param type + inV := fType.In(0) + inKind := inV.Kind() + // get outbound param type + outV := fType.Out(0) + outKind := outV.Kind() + // check types for input and output + if inKind != outKind { + panic("function input type != output type") + } + if reflect.TypeOf(t.slice).Elem().Kind() != inKind { + panic("slice type != map function input type") + } + // create empty slice based on the original slice + origSlice := reflect.ValueOf(t.slice) + newSlice := make([]interface{}, origSlice.Len()) + // apply the method then append the item to the new slice + for i := 0; i < origSlice.Len(); i++ { + value := origSlice.Index(i) + newSlice[i] = v.Call([]reflect.Value{value})[0].Interface() + } + // return new mapped results + return Type{slice: newSlice} +} + +func (t *Type) Get() interface{} { + return t.slice +} diff --git a/src/apply/apply_test.go b/src/apply/apply_test.go new file mode 100644 index 0000000..1e09655 --- /dev/null +++ b/src/apply/apply_test.go @@ -0,0 +1 @@ +package apply_test diff --git a/src/main.go b/src/main.go new file mode 100644 index 0000000..e678980 --- /dev/null +++ b/src/main.go @@ -0,0 +1,16 @@ +package main + +import ( + "fmt" + + "github.com/sghaida/fp/src/apply" +) + +func main() { + data := []int{1, 2, 3, 4, 5, 6, 7, 8} + lifted := apply.Lift(data) + addOne := func(item int) int { return item + 1 } + newData := lifted.Apply(addOne) + fmt.Println(newData.Get()) + fmt.Println(data) +}