functional

package module
v0.0.6 Latest Latest
Warning

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

Go to latest
Published: May 11, 2023 License: MIT Imports: 3 Imported by: 0

README

Go Functional

Go Functional provides Functional Programming capabilities to Go.

Maintenance

Go Reference

Go Report Card

Go version

Go Functional

Sub Packages

The root package functional acts as a namespace for sub-packages that target specific data structures, like slices and maps. It also exposes some common helpers useful for testing and benchmarks. You will rarely need to import it; rather, you will want to import a sub-package, such as Fslice.

Fslice

Fslice provides a set of methods for operating on slices. Methods that could return a slice return an Fslice, making the system chainable. Among them are common functional programming methods, such as:

  • Fslice.Map() - takes a function that maps over every element, returning a transformed slice (chainable)
  • Fslice.Filter() - takes a function that filters a slice to a smaller subset (chainable)
  • Fslice.Includes() - returns true if a value was found in the slice
  • Fslice.Some() - takes a function that returns a boolean. Returns true early if the function returned true once
  • Fslice.Every() - takes a function that returns a boolean. Returns false early if the function returned false once
  • Fslice.ToSlice() - returns the underlying (non-functional) slice
  • Fslice.Reduce() - takes a function that behaves like an accumulator, returning a single value
  • Fslice.Sort() - takes a function that sorts a slice, and returns it (chainable)

Calling it is easy. It works like this:

import (
	"fmt"
	"github.com/sean9999/GoFunctional/fslice"
)

//  Input
inputNums := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}

//  a FilterFunction that returns true if the number is prime
isPrime := func(val int, _ int, _ []int) bool {
    return primes.IsPrime(val)
}

//  a MapFunction that squares a number
square := func(val int, _ int, _ []int) int {
    return val * val
}

//  a slice containing only the primes, squared 
outputNums := fslice.From(inputNums).Filter(isPrime).Map(square)

fmt.Println(outputNums)
// Output: [4 9 25 49 121]

Or you could put your functions inline, which is common in Functional Programming:

outputNums := fslice.From(inputNums).Filter(func(n int, _ int, _ []int) bool {
    return primes.IsPrime(val)
}).Map(func(n int, _ int, _ []int) int {
    return n * n
})

fmt.Println(outputNums)
// Output: [4 9 25 49 121]

Design Goals

  • near-zero cost abstraction, with allowances made for readability and flexibility
  • respectful of both Functional Programming and Go idioms
  • well defined behaviour
  • well tested
  • well benchmarked, so that time and space complexity can be known and documented

What's Next?

A similar set of methods for maps, which will be under a package called Fmap. There might be an opportunity to do something for structs as well. We'll see.

A bothersome limitation of Go Functional is the inability to use different types. I'd like to find an elegant solution to that, leveraging the concept of a Functor.

Benchmarks should be plotted so that performance characteristics can be seen visually, and time and space complexity metrics can be extrapolated.

Some system to measure the rate at which cyclomatic complexity increases as the chain of methods increases, would be useful.

Pull requests welcome.

https://www.seanmacdonald.ca/

Documentation

Overview

Package functional implements Functional Programming capabilities for common go data structures. The root package offers nothing except for some globals, some helper functions, and to act as a namespace for the sub-packages. Sub-packages include pkg/github.com/sean9999/GoFunctional/fslice . "fmap" is on the roadmap. "fstruct" is being considered.

Many methods are chainable, and when possible return another fslice or fmap, rather than the underlying slice or map. This is what gives Go Functional is compasability, expressiveness, and lends it the signature Functional Programming style. enhancing composability and expressiveness, which is what gives functional programming it's signature style.

While for most use-cases Go Functional is _essentially_ a zero-cost abstraction, it is not _fundamentally_ so. There are use cases where the trade-off between expressiveness and performance is not acceptable. Use the right tool for the right job. Run the included benchmarks for performance characteristics, or view Go's cyclomatic complexity here: [https://goreportcard.com/report/github.com/sean9999/GoFunctional]

Example
package main

import (
	"fmt"

	"github.com/fxtlabs/primes"
	"github.com/sean9999/GoFunctional/fslice"
)

func main() {

	//	apply a FilterFunction and then a MapFunction to get squares of primes
	inputNumbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
	outputNumbers := fslice.From(inputNumbers).Filter(func(v int, _ int, _ []int) bool {
		return primes.IsPrime(v)
	}).Map(func(v int, _ int, _ []int) int {
		return v * v
	})
	fmt.Println(outputNumbers)
}
Output:

[4 9 25 49 121]

Index

Examples

Constants

This section is empty.

Variables

View Source
var TestSuite = functionalTestSuite{
	LoremIpsumFilePath: "fslice/testdata/lorem_ipsum_%d_words.txt",
	LoremIpsumLengths:  []int{10, 100, 1_000, 10_000, 100_000},
}

TestSuite provides convenience functions for tests and benchmarks see: ./bin/generate-test-data/ to generate test data

Functions

func FsliceFrom

func FsliceFrom[T comparable](inputSlice []T) fslice.MethodSet[T]

convenience for fslice.From

Example
package main

import (
	"fmt"

	functional "github.com/sean9999/GoFunctional"
	"github.com/sean9999/GoFunctional/fslice"
)

func main() {

	// these methods are functionally equivalent

	// import functional "github.com/sean9999/GoFunctional"
	x := functional.FsliceFrom([]int{1, 2, 3})

	// import "github.com/sean9999/GoFunctional/fslice"
	y := fslice.From([]int{1, 2, 3})

	fmt.Println(x, y)
}
Output:

[1 2 3] [1 2 3]

func NewFslice

func NewFslice[T comparable](length, capacity int) fslice.MethodSet[T]

convenience for fslice.New

Types

This section is empty.

Directories

Path Synopsis
bin
Package fslice implements a set of methods for operating on slices in a Functional Programming way.
Package fslice implements a set of methods for operating on slices in a Functional Programming way.

Jump to

Keyboard shortcuts

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