🐹 Go - Functional Functions
Functional Functions
Updated at 2014-01-24 11:11
Go does not have generics so it is more complicated to build a general purpose "functional programming" library like Underscore for JS or LINQ for C#. But you can define these functions for data types you need.
package main
import (
"fmt"
"strings"
"unicode"
)
// Returns the first index where given value is found, or -1 if not found.
func Index(values []string, other string) int {
for i, value := range values {
if value == other {
return i
}
}
return -1
}
// Returns true if given value is found in the slice.
func Include(values []string, other string) bool {
return Index(values, other) >= 0
}
// Returns true if one elements fulfil the given function.
func Any(values []string, f func(string) bool) bool {
for _, value := range values {
if f(value) {
return true
}
}
return false
}
// Returns true if all elements fulfil the given function.
func All(values []string, f func(string) bool) bool {
for _, value := range values {
if !f(value) {
return false
}
}
return true
}
// Form a new slice that only contains elements that fulfil the given function.
func Filter(values []string, f func(string) bool) []string {
filttered := make([]string, 0)
for _, value := range values {
if f(value) {
filttered = append(filttered, value)
}
}
return filttered
}
// Form a new slice after applying given function to each element.
func Map(values []string, f func(string) string) []string {
mapped := make([]string, len(values))
for i, value := range values {
mapped[i] = f(value)
}
return mapped
}
// Returns the element which has the highest score using given evaluator.
func Max(values []string, f func(string) int) (string, int, bool) {
var maxValue string
var maxScore int
var wasFound = false
for _, value := range values {
score := f(value)
if score > maxScore {
maxValue = value
maxScore = score
wasFound = true
}
}
return maxValue, maxScore, wasFound
}
var p = fmt.Println
func main() {
var fruits = []string{"peach", "apple", "pear", "plum"}
p(Index(fruits, "pear")) // => 2, "pear" is at string[2]
p(Index(fruits, "orange")) // => -1, "orange" does not exist
p(Include(fruits, "plum")) // => true
p(Include(fruits, "grape")) // => false
p(Any(fruits, func(v string) bool {
return strings.HasPrefix(v, "p")
}))
// => true, some of the strings start with "p"
p(All(fruits, func(v string) bool {
return strings.HasPrefix(v, "p")
}))
// => false, not all of the strings start with "p"
p(Filter(fruits, func(v string) bool {
return strings.Contains(v, "e")
}))
// => [peach apple pear]
p(Map(fruits, func(v string) string {
runes := []rune(v)
runes[0] = unicode.ToUpper(runes[0])
str := string(runes)
return str
}))
// => [Peach Apple Pear Plum]
p(Map(fruits, strings.ToUpper))
// => [PEACH APPLE PEAR PLUM]
p(Max(fruits, func(v string) int {
return len(v)
}))
// => peach 5 true
p(Max([]string{}, func(v string) int {
return len(v)
}))
// => "" 0 false
}