maduce

package module
v0.0.0-...-2d7e8ae Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 19, 2021 License: MIT Imports: 1 Imported by: 0

README

maduce

maduce is an implementation of the functional concepts filter, map and reduce found in other languages like python, javascript, etc.

This package purposely diverge from core principals of how go code should be written, you should therefore think twice before you consider using this package, in most cases for loops is the way to go.

The reason for the existence of this package is that it allows for better composability and allows datasets to be more easily explored and evaluated in Go. It's specifically designed as a tool to be used for experimenting with datasets and not as a library intented for production use where performance is critical.

The API of the maduce package is completely dynamic which has the down side of no compile time garuantees about the function signatures given to filter, map or reduce.

Each method on a maduce.Collection have a description of the handlers they support. Because go doesn't support generics yet, i have create my own notation where <Type> can be replaced with what ever type you want. The <Type> in the function argument has to be the same as in the collection. The output type could be something else or the same as the input, it depends on what you want to achieve.

// example of function signature with generic types
func(item <Type>, index int) <Type>

// example of function that maps over a collection of float64 and castst them
// to a string in a new collection, this example satisfies the function
// signature from above
func(item float64, index int) string {
	return fmt.Sprintf("%.2f", item)
}

This package is heavily based on reflection and type assertions which can result in runtime panics if used wrongly.

TODO(@kvartborg): would like to experiment with a streaming implementation based on the io.Reader interface at some point.

Usage

Below is a simple example of how a slice of float64 can be filtered, mapped and reduced into a string.

package main

import (
    "fmt"

    "github.com/kvartborg/maduce"
)

func main() {
  collection := maduce.From([]float64{0, 1.8, 2, 3.3, 4, 5})

  var result string
  collection.
    Filter(func(n float64) bool {
      return n > 0
    }).
    Map(func(n float64) string {
      return fmt.Sprintf("%.2f", n)
    }).
    Reduce(&result, func(s, result string, index int) string {
      if result == "" {
        return fmt.Sprintf("%d: %s", index, s)
      }
      return fmt.Sprintf("%s\n%d: %s", result, index, s)
    })

  fmt.Println(result)
}

Documentation

The full documentation of the package can be found on godoc.

License

This project is licensed under the MIT License.

Documentation

Overview

Package maduce is an implementation of the functional concepts filter, map and reduce found in other languages like python, javascript, etc.

This package purposely diverge from core principals of how go code should be written, you should therefore think twice before you consider using this package, in most cases for loops is the way to go.

The reason for the existence of this package is that it allows for better composability and allows datasets to be more easily explored and evaluated in Go. It's specifically designed as a tool to be used for experimenting with datasets and not as a library intented for production use where performance is critical.

The API of the maduce package is completely dynamic which has the down side of no compile time garuantees about the function signatures given to filter, map or reduce.

Each method on a maduce.Collection have a description of the handlers they support. Because go doesn't support generics yet, i have create my own notation where <Type> can be replaced with what ever type you want. The <Type> in the function argument has to be the same as in the collection. The output type could be something else or the same as the input, it depends on what you want to achieve.

// example of function signature with generic types
func(item <Type>, index int) <Type>

// example of function that maps over a collection of float64 and castst them
// to a string in a new collection, this example satisfies the function
// signature from above
func(item float64, index int) string {
	return fmt.Sprintf("%.2f", item)
}

This package is heavily based on reflection and type assertions which can result in runtime panics if used wrongly.

TODO(@kvartborg): would like to experiment with a streaming implementation based on the io.Reader interface at some point.

Example
package main

import (
	"fmt"

	"github.com/kvartborg/maduce"
)

func main() {
	collection := maduce.From([]float64{0, 1.8, 2, 3.3, 4, 5})

	var result string
	collection.
		Filter(func(n float64) bool {
			return n > 0
		}).
		Map(func(n float64) string {
			return fmt.Sprintf("%.2f", n)
		}).
		Reduce(&result, func(s, result string, index int) string {
			if result == "" {
				return fmt.Sprintf("%d: %s", index, s)
			}
			return fmt.Sprintf("%s\n%d: %s", result, index, s)
		})

	fmt.Println(result)
}
Output:
0: 1.80
1: 2.00
2: 3.30
3: 4.00
4: 5.00

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Collection

type Collection []interface{}

Collection is a list of what ever type you can think of, it is even possible to have different types contained within the same collection.

NOTE: Strive to keep a single type in a collection otherwise you may experience panics if your filter, map or reduce functions isn't type agnostic.

func From

func From(slice interface{}) Collection

From takes a slice of some type and turns it into a collection.

func (Collection) Filter

func (c Collection) Filter(filter interface{}) Collection

Filter takes a function which evaluates whether an item should be in the collection. Items will stay in the collection if the filter function returns true.

The following function signatures are supported for filtering:

func(item <Type>) bool
func(item <Type>, index int) bool

A common way to delete something from a collection is to simply filter based on index or some other uniq identifier.

// Delete integer with index 1
result := maduce.Collection{1, 2, 3}.Filter(func (_, index int) bool { return index != 1})
Example
package main

import (
	"fmt"

	"github.com/kvartborg/maduce"
)

func main() {
	collection := maduce.From([]int{1, 2, 3, 4, 5})

	result := collection.Filter(func(n int) bool {
		return n > 3
	})

	fmt.Println(result)
}
Output:
[4 5]

func (Collection) Map

func (c Collection) Map(mapper interface{}) Collection

Map takes a mapper function which transforms or mutates items and returns them in a new collection.

The following function signatures are supported for mappers

func(item <Type>) <Type>
func(item <Type>, index int) <Type>
Example
package main

import (
	"fmt"
	"strconv"

	"github.com/kvartborg/maduce"
)

func main() {
	collection := maduce.From([]int{1, 2, 3, 4, 5})

	result := collection.Map(func(n int) string {
		return strconv.Itoa(n)
	})

	fmt.Printf("%#v\n", result)
}
Output:
maduce.Collection{"1", "2", "3", "4", "5"}

func (Collection) Reduce

func (c Collection) Reduce(receiver, reducer interface{})

Reduce takes a receiver and a reducer function.

The following function signatures are supported for reducers:

func(item <Type>, receiver <Type>) <Type>
func(item <Type>, receiver <Type>, index int) <Type>
Example
package main

import (
	"fmt"

	"github.com/kvartborg/maduce"
)

func main() {
	collection := maduce.From([]int{1, 2, 3, 4, 5})

	var sum int
	collection.Reduce(&sum, func(n, sum int) int {
		return n + sum
	})

	fmt.Println(sum)
}
Output:
15

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL