functional

package module
v0.0.8 Latest Latest
Warning

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

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

README

Go Functional

Go Functional provides Functional Programming capabilities to Go.

Maintenance

Go Reference

Go Report Card

Go version

Go Functional

Read the blog post here:

Root package

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.

Sub Packages

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:

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

While generic, Go Functional is not fully polymorphic. I'd like to find an elegant way to provide this, using the concept of a Functor.

There is no reason Go Functional could not provide an elegant and idiomatic set-builder.

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 are most welcome.

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

This section is empty.

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