# Implement Higher Order Functions in Go Lang – Map, Reduce and Filter

Higher-order functions are a fundamental concept in functional programming, and Go is no exception. In some time ago we explored how to implement some of the higher order functions in Python,you can check out the video here .

In this tutorial we will learn how to implement them in Go.

In Go, higher-order functions are functions that take other functions as arguments or return functions as output. In this article, we’ll explore how to implement three common higher-order functions in Go: `map``reduce`, and `filter`. We’ll also touch on the `zip` function, which is not strictly a higher-order function but is often used in conjunction with higher-order functions.

#### Map Function

The `map` function takes a function and a slice of inputs (or sequence), and applies the function to each input in the slice, returning a new slice of outputs. Here’s an example implementation of `map` in Go:

First we will implement a map function that accepts only integer and return a slice of integer and then we will make it more robust to support other data types via Go Generics.

```func myMap(sequence []int, fn func(int) int) []int {
results := []int{}
for _, i := range sequence {
results = append(results, fn(i))
}
return results
}```

How do we use this our custom map function

```package main

import "fmt"

// our function
func multiply6(a float64) float64 {
return a * 6
}

func main(){
results := myMap([]int{2,4,6,7},multiply6)
fmt.Println(results)
}```

How do we support other data types? To do so we will use Go Generics (T) and create a generic function

```func myMap[T, U any](fn func(T) U, inputs []T) []U {
outputs := make([]U, len(inputs))
for i, input := range inputs {
outputs[i] = fn(input)
}
return outputs
}```

This implementation takes a function `fn` that takes a single input of type `T` and returns a single output of type `U`. It also takes a slice of inputs `inputs` of type `[]T`. The function returns a new slice of outputs `outputs` of type `[]U`.

The order of the argument in this function was changed to make it more like how map is used in python.

To use `map`, we can define a function that takes a string and returns its uppercase version, and then apply it to a slice of strings:

```func toUpper(s string) string {
return strings.ToUpper(s)
}

inputs := []string{"hello", "world", "go"}
outputs := myMap(toUpper, inputs)
fmt.Println(outputs) // Output: ["HELLO", "WORLD", "GO"]
// or with support for int
results := myMap(multiply6,[]int{2,4,6,7})```

#### Reduce

The `reduce` function takes a function, an initial value, and a slice of inputs, and applies the function to each input in the slice, starting with the initial value. The function returns the final result of the reduction. Here’s an example implementation of `reduce` in Go:

```func myReduce[T, V any](fn func(V, T) V,sequence []T,  initValue V) V {
acc := initValue
for _, i := range sequence {
fmt.Println("Initial", acc)
acc = fn(acc, i)
fmt.Println("Current", acc)
}
return acc
}
```

This implementation takes a function `fn` that takes two inputs of type `T` and returns a single output of type `T`. It also takes an initial value of type `T` and a slice of inputs `inputs` of type `[]T`. The function returns the final result of the reduction, which has type `T`.

How do we apply the custom reduce function then?

```func find_max(a, b int) int {
if a > b {
return a
} else {
return b
}
}

max_values := myreduce(find_max,[]int{1, 3, 2, 10, 5, 6, 7},  0)
fmt.Println(max_values)```

We can also use the idea behind reduce to implement a sum of a list or sequence.

```func add(a, b int) int {
return a + b
}

inputs := []int{1, 2, 3, 4, 5}
fmt.Println(result) // Output: 15```

#### Filter

The `filter` function takes a function and a slice of inputs, and returns a new slice of inputs that satisfy the condition defined by the function. Here’s an example implementation of `filter` in Go:

```// filter: sequence if condition is meet it returns those that meet the condition
func myFilter(fn func(int) bool,sequence []int) []int {
results := []int{}
for _, v := range sequence {
if fn(v) {
results = append(results, v)
}
}
return results
}

// support for any data type via generics
func Filter[T any](fn func(T) bool, inputs []T) []T {
var outputs []T
for _, input := range inputs {
if fn(input) {
outputs = append(outputs, input)
}
}
return outputs
}```

This implementation takes a function `fn` that takes a single input of type `T` and returns a boolean value indicating whether the input satisfies the condition. It also takes a slice of inputs `inputs` of type `[]T`. The function returns a new slice of inputs `outputs` that satisfy the condition, which has type `[]T`.

To use `filter`, we can define a function that takes a number and returns true if the condition is meet, and then apply it to a slice of numbers:

```func greaterThanZero(n int) bool {
return n > 0
}

func isOdd(x int) bool {
return x%2 == 1
}

inputs := []int{-1, 0, 1, 2, 3}
outputs := Filter(greaterThanZero, inputs)
fmt.Println(outputs) // Output: [1, 2, 3]

odd_values := myfilter(isOdd,[]int{1, 3, 2, 10, 5, 6, 7})
fmt.Println(odd_values)```

#### Zip

The `zip` function takes two or more slices of the same length and returns a slice of tuples, where each tuple contains a value from each slice. Here’s an example implementation of `zip` in Go:

```func Zip[T any](slices ...[]T) [][]T {
var outputs [][]T
for i := range slices {
output := make([]T, len(slices))
for j, slice := range slices {
output[j] = slice[i]
}
outputs = append(outputs, output)
}
return outputs
}```

This implementation takes a variable number of slices `slices` of type `[]T`, where `T` is a type parameter. The function returns a slice of tuples `outputs` of type `[][]T`.To use `zip`, we can define two slices of strings and apply them to `zip`:

```input1 := []string{"hello", "world", "go"}
input2 := []string{"there", "you", "are"}
outputs := Zip(input1, input2)
fmt.Println(outputs) // Output: [["hello" "there"], ["world" "you"], ["go" "are"]]```

In this example, `input1` and `input2` are two slices of strings, and `Zip` returns a slice of tuples, where each tuple contains a string from `input1` and a string from `input2`.

You can check out the video tutorial for these implementation below

In this post we’ve explored how to implement higher-order functions in Go, including `map``reduce``filter`, and `zip`. These functions are powerful tools for manipulating and transforming data , and can help you write more concise and expressive code.