fuego

package module
v6.2.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Feb 17, 2019 License: Apache-2.0 Imports: 4 Imported by: 0

README

fuego - Functional Experiment in Go

godoc goreportcard cover.run

Overview

Making Go come to functional programming.

This is a research project in functional programming which I hope will prove useful!

Fuego brings a few functional paradigms to Go. The intent is to save development time while promoting code readability and reduce the risk of complex bugs.

Install

go get github.com/seborama/fuego

Or for a specific version:

go get gopkg.in/seborama/fuego.v6

Contribute

Contributions and feedback are welcome.

As this project is still in early stages, large portions of the code get crafted and thrown away.

For contributions, you must develop in TDD fashion and ideally provide Go testable examples (if meaningful).

The Golden rules of the game

1- Producers close their channel. In other words, when you create a channel, you are responsible for closing it. Similarly, whenever fuego creates a channel, it is responsible for closing it.

2- Consumers do not close channels.

3- Producers and consumers should be running in separate Go routines to prevent deadlocks when the channels' buffers fill up.

Pressure

Go channels support buffering that affect the behaviour when combining channels in a pipeline.

When a consumer Stream's channel buffer is full, the producer will not be able to send more data through to it. This protects downstream operations from overloading.

Presently, a Go channel cannot dynamically change its buffer size. This prevents from adapting the stream flexibly. Constructs that use 'select' on channels on the producer side can offer opportunities for mitigation.

Main features

The code documentation can be found on godoc.

The tests form the best source of documentation. Fuego comes with a good collection of unit tests and testable Go examples. Don't be shy, open them up and read them and tinker with them!

Note however that most tests use unbuffered channels to help detect deadlocks. On real life scenarios, it is recommended to use buffered channels for increased performance.

Have fun!!

Entry

Entry is inspired by hamt.Entry. This is an elegant solution from Yota Toyama: the type can be anything so long as it respects the simple behaviour of hamt.Entry. This provides an abstraction of types yet with known behaviour:

  • Hash(): identifies an Entry Uniquely.
  • Equal(): defines equality for a type of Entry. Equal() is expected to be based on Hash().

Several Entry implementations are provided:

  • EntryBool
  • EntryInt
  • EntryFloat
  • EntryString
  • EntryMap
  • EntrySlice
EntryMap

This is a map of Entry defined as:

type EntryMap map[Entry]EntrySlice

GroupBy methods use an EntryMap to return data.

It is important to remember that maps are not ordered.

EntrySlice

This is an ordered slice of Entry elements which signature is:

type EntrySlice []Entry
Maybe

A Maybe represents an optional value.

When the value is nil, Maybe is considered empty unless it was created with MaybeSome() in which case it is considered to hold the nil value.

MaybeNone() always produces an empty optional.

Tuple

fuego provides these Tuple's:

  • Tuple0
  • Tuple1
  • Tuple2

The values of fuego Tuples are of type Entry.

Consumer

Consumer is a kind of side-effect function that accepts one argument and does not return any value.

type Consumer func(i Entry)
Functions

See example_function_test.go for basic example uses of Function and BiFunction and the other tests / examples for more uses.

Function

A Function is a normal Go function which signature is:

func(i Entry) Entry
BiFunction

A BiFunction is a normal Go function which signature is:

func(i,j Entry) Entry

BiFunction's are used with Stream.Reduce() for instance, as seen in stream_test.go.

ToIntFunction

This is a special case of Function used to convert a Stream to an IntStream.

type ToIntFunction func(e Entry) EntryInt
Stream

A Stream is a wrapper over a Go channel.

Note that 'nil' channels are prohibited.

NOTE:

Concurrent streams are challenging to implement owing to ordering issues in parallel processing. At the moment, the view is that the most sensible approach is to delegate control to users. Multiple fuego streams can be created and data distributed across as desired. This empowers users of fuego to implement the desired behaviour of their pipelines.

Creation

When providing a Go channel to create a Stream, beware that until you close the channel, the Stream's internal Go function that processes the data on the channel will remain active. It will block until either new data is produced or the channel is closed by the producer. When a producer forgets to close the channel, the Go function will stray.

Streams created from a slice do not suffer from this issue because they are closed when the slice content is fully pushed to the Stream.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryInt(1),
    ƒ.EntryInt(2),
    ƒ.EntryInt(3),
}, 1e3)
// or if you already have a channel of Entry:
c := make(chan ƒ.Entry) // you could add a buffer size as a second arg, if desired
go func() {
    defer close(c)
    c <- ƒ.EntryString("one")
    c <- ƒ.EntryString("two")
    c <- ƒ.EntryString("three")
    // c <- ...
}()
NewStream(c)
Filter
// See helpers_test.go for "newEntryIntEqualsTo()"
s := ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryInt(1),
    ƒ.EntryInt(2),
    ƒ.EntryInt(3),
}, 0)

s.Filter(
        FunctionPredicate(entryIntEqualsTo(ƒ.EntryInt(1))).
            Or(
                FunctionPredicate(entryIntEqualsTo(ƒ.EntryInt(3)))),
)

// returns []ƒ.EntryInt{1,3}
Reduce / LeftReduce
// See helpers_test.go for "concatenateStringsBiFunc()"
ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("four"),
    ƒ.EntryString("twelve)",
    ƒ.EntryString("one"),
    ƒ.EntryString("six"),
    ƒ.EntryString("three"),
}, 1e3).
    Reduce(concatenateStringsBiFunc)
// returns ƒ.EntryString("four-twelve-one-six-three")
ForEach
total := 0

computeSumTotal := func(value ƒ.Entry) {
    total += int(value.(ƒ.EntryInt).Value())
}

s := ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryInt(1),
    ƒ.EntryInt(2),
    ƒ.EntryInt(3),
}, 0).
    ForEach(calculateSumTotal)
// total == 6
Intersperse
ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("four"),
}, 1e3).
    Intersperse(ƒ.EntryString(" - "))
// "three - two - four"
GroupBy

Please refer to stream_test.go for an example that groups numbers by parity (odd / even).

Count

Counts the number of elements in the Stream.

AnyMatch

Returns true if any of the elements in the stream satisfies the Predicate argument.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("four"),
}, 1e3).
    AnyMatch(func(e ƒ.Entry) bool {
        return e.Equal(ƒ.EntryString("three"))
    })
// true
NoneMatch

Returns true if none of the elements in the stream satisfies the Predicate argument.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("four"),
}, 1e3).
    NoneMatch(func(e ƒ.Entry) bool { return e.Equal(ƒ.EntryString("nothing like this")) })
// true
AllMatch

Returns true if every element in the stream satisfies the Predicate argument.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("fourth"),
}, 1e3).
    AllMatch(func(e ƒ.Entry) bool {
        return strings.Contains(string(e.(ƒ.EntryString)), "t")
    })
// true
Drop

Drops the first 'n' elements of the stream and returns a new stream.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("fourth"),
}, 1e3).
    Drop(2)
// Stream of ƒ.EntryString("fourth")
DropWhile

Drops the first elements of the stream while the predicate satisfies and returns a new stream.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("fourth"),
}, 1e3).
    DropWhile(func(e ƒ.Entry) bool {
        return e.Equal(ƒ.EntryString("three"))
    })
// Stream of ƒ.EntryString("two") and ƒ.EntryString("fourth")
DropUntil

Drops the first elements of the stream until the predicate satisfies and returns a new stream.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("fourth"),
}, 1e3).
    DropUntil(func(e ƒ.Entry) bool {
        return e.Equal(ƒ.EntryString("fourth"))
    })
// Stream of ƒ.EntryString("three") and ƒ.EntryString("two")
Last

Returns the last element of the stream.

This is a special case of LastN(1) which returns a single Entry.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("fourth"),
}, 1e3).
    Last()
// ƒ.EntryString("fourth")
LastN

Return a slice of the last N elements of the stream.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("fourth"),
}, 1e3).
    LastN(2)
// []ƒ.Entry{ƒ.EntryString("two"), ƒ.EntryString("fourth")}
EndsWith

Return true if the stream ends with the supplied slice of elements.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("fourth"),
}, 1e3).
    EndsWith([]ƒ.Entry{ƒ.EntryString("two"), ƒ.EntryString("fourth")})
// true
Head

Returns the first Entry of the stream.

This is a special case of HeadN(1) which returns a single Entry.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("fourth"),
}, 1e3).
    Head()
// ƒ.EntryString("three")
HeadN

Return a slice of the first N elements of the stream.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("fourth"),
}, 1e3).
    HeadN(2)
// []ƒ.Entry{ƒ.EntryString("three"), ƒ.EntryString("two")}
StartsWith

Return true if the stream starts with the supplied slice of elements.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("fourth"),
}, 1e3).
    StartsWith([]ƒ.Entry{ƒ.EntryString("three"), ƒ.EntryString("two")})
// true
Take

Takes the first 'n' elements of the stream and returns a new stream.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("fourth"),
}, 1e3).
    Take(2)
// Stream of []ƒ.Entry{ƒ.EntryString("three"), ƒ.EntryString("two")}
TakeWhile

Takes the first elements of the stream while the predicate satisfies and returns a new stream.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("fourth"),
}, 1e3).
    TakeWhile(func(e ƒ.Entry) bool {
        return strings.HasPrefix(string(e.(ƒ.EntryString)), "t")
    })
// Stream of []ƒ.Entry{ƒ.EntryString("three"), ƒ.EntryString("two")}
TakeUntil

Takes the first elements of the stream until the predicate satisfies and returns a new stream.

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("fourth"),
}, 1e3).
    TakeUntil(func(e ƒ.Entry) bool {
        return e.Equal(ƒ.EntryString("fourth"))
    })
// Stream of []ƒ.Entry{ƒ.EntryString("three"), ƒ.EntryString("two")}
IntStream

A Stream of EntryInt.

It contains all of the methods Stream exposes and additional methods that pertain to an EntryInt stream such as aggregate functions (Sum(), Average(), etc).

Note that 'nil' channels are prohibited.

NOTE: The current implementation is based on Stream and an intermediary channel that converts incoming EntryInt elements to Entry. This approach offers programming conciseness but the use of an intermediary channel likely decreases performance. This also means that type checking is weak on methods "borrowed" from Stream that expect Entry (instead of EntryInt).

Stream methods

All methods that pertain to Stream are available to IntStream.

Max

Returns the greatest element in the stream.

Min

Returns the smallest element in the stream.

Sum

Returns the sum of all elements in the stream.

Average

Returns the average of all elements in the stream.

FloatStream

A Stream of EntryFloat. It is akin to IntStream but for EntryFloat's.

Note that 'nil' channels are prohibited.

It contains all of the methods Stream exposes and additional methods that pertain to an EntryFloat stream such as aggregate functions (Sum(), Average(), etc).

NOTE: The current implementation is based on Stream and an intermediary channel that converts incoming EntryFloat elements to Entry. This approach offers programming conciseness but the use of an intermediary channel likely decreases performance. This also means that type checking is weak on methods "borrowed" from Stream that expect Entry (instead of EntryFloat).

Stream methods

All methods that pertain to Stream are available to FloatStream.

Max

Returns the greatest element in the stream.

Min

Returns the smallest element in the stream.

Sum

Returns the sum of all elements in the stream.

Average

Returns the average of all elements in the stream.

Predicates

A Predicate is a normal Go function which signature is:

type Predicate func(t Entry) bool

A Predicate has convenient pre-defined methods:

  • Or
  • And
  • Not
  • Xor

Several pre-defined Predicate's exist too:

  • True
  • False
  • FunctionPredicate - a Predicate that wraps over a Function

See example_predicate_test.go for some examples.

// ƒ is ALT+f on Mac. For other OSes, search the internet,  for instance,  this page: https://en.wikipedia.org/wiki/%C6%91#Appearance_in_computer_fonts
    _ = ƒ.Predicate(ƒ.False).
        ƒ.And(Predicate(ƒ.False).
            ƒ.Or(ƒ.True))(ƒ.EntryInt(1)) // returns false

res := ƒ.Predicate(intGreaterThanPredicate(50)).
        And(ƒ.True).
        Negate()(ƒ.EntryInt(23)) // res = true

func intGreaterThanPredicate(rhs int) ƒ.Predicate {
    return func(lhs ƒ.Entry) bool {
        return int(lhs.(ƒ.EntryInt)) > rhs
    }
}

Known limitations

  • several operations may be memory intensive or poorly performing.

Documentation

Index

Examples

Constants

View Source
const PanicMissingChannel = "stream creation requires a channel"

PanicMissingChannel signifies that the Stream is missing a channel.

View Source
const PanicNoSuchElement = "no such element"

PanicNoSuchElement signifies that the requested element is not present.

Variables

This section is empty.

Functions

func False

func False(t Entry) bool

False is a predicate that returns always false.

func True

func True(t Entry) bool

True is a predicate that returns always true.

Types

type BiFunction

type BiFunction func(e1, e2 Entry) Entry

BiFunction that accepts two arguments and produces a result.

Example

ExampleBiFunction shows how to use BiFunction's. There are more interesting examples through the code. Search for `BiFunction` or the BiFunction signature.

data := []ƒ.Entry{
	EntryString("four"),
	EntryString("twelve"),
	EntryString("one"),
	EntryString("six"),
	EntryString("three")}

res := ƒ.NewStreamFromSlice(data, 0).
	Reduce(concatenateStringsBiFunc)

fmt.Printf("res = %+v\n", res)
Output:

res = four-twelve-one-six-three

type Consumer

type Consumer func(i Entry)

Consumer that accepts one argument and does not return any value.

type Entry

type Entry interface {
	Hash() uint32 // TODO: remove Hash() since the project no longer includes collections? Hashes suffer from collision.
	Equal(Entry) bool
}

Entry is the simplest behaviour that functional types must adhere to.

type EntryBool

type EntryBool bool

EntryBool is an Entry for 'bool'.

func (EntryBool) Equal

func (eb EntryBool) Equal(e Entry) bool

Equal returns true if this type is equal to 'e'.

func (EntryBool) Hash

func (eb EntryBool) Hash() uint32

Hash returns a hash for this Entry.

type EntryFloat

type EntryFloat float32

EntryFloat is an Entry for 'float32'.

func (EntryFloat) Equal

func (f EntryFloat) Equal(e Entry) bool

Equal returns true if 'e' and 'f' are equal.

func (EntryFloat) Hash

func (f EntryFloat) Hash() uint32

Hash returns a hash for 'f'.

type EntryInt

type EntryInt int

EntryInt is an Entry for 'int'.

func (EntryInt) Equal

func (i EntryInt) Equal(e Entry) bool

Equal returns true if 'e' and 'i' are equal.

func (EntryInt) Hash

func (i EntryInt) Hash() uint32

Hash returns a hash for 'i'.

type EntryMap

type EntryMap map[Entry]EntrySlice

EntryMap is an Entry for 'map[Entry]EntrySlice'.

func (EntryMap) Equal

func (em EntryMap) Equal(e Entry) bool

Equal returns true if this type is equal to 'e'.

func (EntryMap) Hash

func (em EntryMap) Hash() uint32

Hash returns a hash for this Entry.

func (EntryMap) Stream

func (em EntryMap) Stream(bufsize int) Stream

Stream returns a stream of tuples the elements of the EntryMap.

type EntrySlice

type EntrySlice []Entry

EntrySlice is an Entry for '[]Entry'.

func (EntrySlice) Equal

func (es EntrySlice) Equal(e Entry) bool

Equal returns true if this type is equal to 'e'.

func (EntrySlice) Hash

func (es EntrySlice) Hash() uint32

Hash returns a hash for this Entry.

type EntryString

type EntryString string

EntryString is an Entry for 'string'.

func (EntryString) Equal

func (es EntryString) Equal(e Entry) bool

Equal returns true if 'e' and 'i' are equal.

func (EntryString) Hash

func (es EntryString) Hash() uint32

Hash returns a hash for 'i'.

func (EntryString) Len

func (es EntryString) Len() EntryInt

Len transform the string to lower case.

func (EntryString) ToLower

func (es EntryString) ToLower() EntryString

ToLower transform the string to lower case.

func (EntryString) ToUpper

func (es EntryString) ToUpper() EntryString

ToUpper transform the string to upper case.

type FloatStream

type FloatStream struct {
	Stream
}

FloatStream is a sequence of EntryFloat elements supporting sequential and (in the future?) parallel operations.

func NewFloatStream

func NewFloatStream(c chan EntryFloat) FloatStream

NewFloatStream creates a new FloatStream. This function leaves the provided channel is the same state of openness.

func NewFloatStreamFromSlice

func NewFloatStreamFromSlice(is []EntryFloat, bufsize int) FloatStream

NewFloatStreamFromSlice creates a new FloatStream from a Go slice of EntryFloat. The stream will be closed once all the slice data has been published.

func (FloatStream) Average

func (is FloatStream) Average() EntryFloat

Average returns the average of the numbers in the stream. Panics if the channel is nil or the stream is empty. This is a special case of a reduction. This is a terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

func (FloatStream) Max

func (is FloatStream) Max() EntryFloat

Max returns the largest number in the stream. Panics if the channel is nil or the stream is empty. This is a special case of a reduction and is equivalent to:

is.Reduce(max) // where max is a BiFunction that returns
               // the largest of two integers.

This is a terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

func (FloatStream) Min

func (is FloatStream) Min() EntryFloat

Min returns the smallest number in the stream. Panics if the channel is nil or the stream is empty. This is a special case of a reduction and is equivalent to:

is.Reduce(min) // where min is a BiFunction that returns
               // the smallest of two integers.

This is a terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

func (FloatStream) Sum

func (is FloatStream) Sum() EntryFloat

Sum adds the numbers in the stream. Panics if the channel is nil or the stream is empty. This is a special case of a reduction and is equivalent to:

is.Reduce(sum) // where max is a BiFunction that adds
               // two integers.

This is a terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

type Function

type Function func(e Entry) Entry

Function that accepts one argument and produces a result.

Example

ExampleFunction shows how to use Function's. There are more interesting examples through the code. Search for `Function` or the Function signature.

timesTwoFunction := timesTwo()
res := timesTwoFunction(ƒ.EntryInt(7))
fmt.Printf("res = %+v\n", res)
Output:

res = 14

type Functor

type Functor struct {
}

A Functor is a functor TODO: does it make sense to implement this in Golang?

type IntStream

type IntStream struct {
	Stream
}

IntStream is a sequence of EntryInt elements supporting sequential and (in the future?) parallel operations.

func NewIntStream

func NewIntStream(c chan EntryInt) IntStream

NewIntStream creates a new IntStream. This function leaves the provided channel is the same state of openness.

func NewIntStreamFromSlice

func NewIntStreamFromSlice(is []EntryInt, bufsize int) IntStream

NewIntStreamFromSlice creates a new IntStream from a Go slice of EntryInt. The stream will be closed once all the slice data has been published.

func (IntStream) Average

func (is IntStream) Average() EntryInt

Average returns the average of the numbers in the stream. Panics if the channel is nil or the stream is empty. This is a special case of a reduction. This is a terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

func (IntStream) Max

func (is IntStream) Max() EntryInt

Max returns the largest number in the stream. Panics if the channel is nil or the stream is empty. This is a special case of a reduction and is equivalent to:

is.Reduce(max) // where max is a BiFunction that returns
               // the largest of two integers.

This is a terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

func (IntStream) Min

func (is IntStream) Min() EntryInt

Min returns the smallest number in the stream. Panics if the channel is nil or the stream is empty. This is a special case of a reduction and is equivalent to:

is.Reduce(min) // where min is a BiFunction that returns
               // the smallest of two integers.

This is a terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

func (IntStream) Sum

func (is IntStream) Sum() EntryInt

Sum adds the numbers in the stream. Panics if the channel is nil or the stream is empty. This is a special case of a reduction and is equivalent to:

is.Reduce(sum) // where max is a BiFunction that adds
               // two integers.

This is a terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

type Maybe

type Maybe struct {
	// contains filtered or unexported fields
}

A Maybe is a maybe monad.

Example

ExampleMaybe shows ways to use a Maybe.

m1 := ƒ.MaybeOf(EntryString("Hello World"))
fmt.Printf("m1.Get=%v\n", m1.Get())
fmt.Printf("m1.GetOrElse=%v\n", m1.GetOrElse(EntryString("Bonjour le monde")))

m2 := ƒ.MaybeOf(nil)
if assert.PanicsWithValue(nil, ƒ.PanicNoSuchElement, func() {
	fmt.Printf("m2.Get=%v\n", m2.Get())
}) {
	fmt.Println("m2.Get() panics with ƒ.PanicNoSuchElement")
}

fmt.Printf("m2.GetOrElse=%v\n", m2.GetOrElse(EntryString("Bonjour le monde")))
Output:

m1.Get=Hello World
m1.GetOrElse=Hello World
m2.Get() panics with ƒ.PanicNoSuchElement
m2.GetOrElse=Bonjour le monde

func MaybeNone

func MaybeNone() Maybe

MaybeNone is a Maybe that does not have a value.

func MaybeOf

func MaybeOf(i Entry) Maybe

MaybeOf creates a new Maybe with the given value. If the value is nil then return None otherwise Some(value). Note: MaybeOf(nil) == None() whereas MaybeSome(nil) == MaybeSome(nil).

func MaybeSome

func MaybeSome(i Entry) Maybe

MaybeSome creates a new Maybe with the given value. Note: MaybeOf(nil) == None() whereas MaybeSome(nil) == MaybeSome(nil).

func (Maybe) Get

func (m Maybe) Get() Entry

Get the value of this Maybe or panic if none exists.

func (Maybe) GetOrElse

func (m Maybe) GetOrElse(e Entry) Entry

GetOrElse gets the value of this Maybe or the given Entry if none exists.

func (Maybe) IsEmpty

func (m Maybe) IsEmpty() bool

IsEmpty returns true when this Maybe does not have a value.

func (Maybe) OrElse

func (m Maybe) OrElse(other Maybe) Maybe

OrElse returns this Maybe or the given Maybe if this Maybe is empty.

type Predicate

type Predicate func(t Entry) bool // TODO return EntryBool instead of bool??

Predicate represents a predicate (boolean-valued function) of one argument.

Example

ExamplePredicate shows how to use and combine Predicates.

package main

import (
	"fmt"

	ƒ "github.com/seborama/fuego"
)

func main() {
	res := ƒ.Predicate(ƒ.False).Negate()(ƒ.EntryInt(1))
	fmt.Printf("Not False == %+v\n", res)

	res = ƒ.Predicate(ƒ.True).And(ƒ.False)(ƒ.EntryInt(1))
	fmt.Printf("True and False == %+v\n", res)

	res = ƒ.Predicate(ƒ.True).Or(ƒ.False)(ƒ.EntryInt(1))
	fmt.Printf("True or False == %+v\n", res)

	// You can use associativity too - part 1 of 2:
	// False And False Or True == true
	res = ƒ.Predicate(ƒ.False).And(ƒ.False).Or(ƒ.True)(ƒ.EntryInt(1))
	fmt.Printf("False And False Or True == %+v\n", res)

	// You can use associativity too - part 2 of 2:
	// False And (False Or True) == false
	res = ƒ.Predicate(ƒ.False).And(ƒ.Predicate(ƒ.False).Or(ƒ.True))(ƒ.EntryInt(1))
	fmt.Printf("False And (False Or True) == %+v\n", res)

}
Output:

Not False == true
True and False == false
True or False == true
False And False Or True == true
False And (False Or True) == false
Example (FunctionPredicate)

ExamplePredicate_custom1 shows how to create a custom Predicate using the utility function ƒ.FunctionPredicate().

isEvenNumberPredicate := ƒ.FunctionPredicate(isEvenNumberFunction)

res := isEvenNumberPredicate.And(ƒ.True)(ƒ.EntryInt(23))
fmt.Printf("res = %v", res)
Output:

res = false
Example (Predicate)

ExamplePredicate_custom2 shows how to create a custom Predicate from scratch. Notice how we get all Predicate helpers (And, Or, Not, etc) for "free".

res := intGreaterThanPredicate(50).And(ƒ.True).Negate()(ƒ.EntryInt(23))
fmt.Printf("res = %v", res)
Output:

res = true

func FunctionPredicate

func FunctionPredicate(f Function) Predicate

FunctionPredicate creates a Predicate from a Function.

func (Predicate) And

func (p Predicate) And(other Predicate) Predicate

And is a composed predicate that represents a short-circuiting logical AND of this predicate and another.

func (Predicate) Negate

func (p Predicate) Negate() Predicate

Negate is an alias for Not().

func (Predicate) Not

func (p Predicate) Not() Predicate

Not is the logical negation of a predicate.

func (Predicate) Or

func (p Predicate) Or(other Predicate) Predicate

Or is a composed predicate that represents a short-circuiting logical OR of two predicates.

func (Predicate) Xor

func (p Predicate) Xor(other Predicate) Predicate

Xor is a composed predicate that represents a short-circuiting logical XOR of two predicates.

type Stream

type Stream struct {
	// contains filtered or unexported fields
}

Stream is a sequence of elements supporting sequential and (in the future?) parallel operations.

func NewStream

func NewStream(c chan Entry) Stream

NewStream creates a new Stream. This function leaves the provided channel is the same state of openness.

func NewStreamFromSlice

func NewStreamFromSlice(slice []Entry, bufsize int) Stream

NewStreamFromSlice creates a new Stream from a Go slice. The slice data is published to the stream after which the stream is closed.

func (Stream) AllMatch

func (s Stream) AllMatch(p Predicate) bool

AllMatch returns whether all of the elements in the stream satisfy the predicate. This is a continuous terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

func (Stream) AnyMatch

func (s Stream) AnyMatch(p Predicate) bool

AnyMatch returns whether any of the elements in the stream satisfies the predicate. This is a continuous terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

func (Stream) Count

func (s Stream) Count() int

Count the number of elements in the stream. This is a special case of a reduction and is equivalent to:

s.MapToInt(func(Entry) { return EntryInt(1) }).Sum()

This is a continuous terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

func (Stream) Drop

func (s Stream) Drop(n uint64) Stream

Drop the first 'n' elements of this stream and returns a new stream.

func (Stream) DropUntil

func (s Stream) DropUntil(p Predicate) Stream

DropUntil drops the first elements of this stream until the predicate is satisfied and returns a new stream. This function streams continuously until the in-stream is closed at which point the out-stream will be closed too.

func (Stream) DropWhile

func (s Stream) DropWhile(p Predicate) Stream

DropWhile drops the first elements of this stream while the predicate is satisfied and returns a new stream. This function streams continuously until the in-stream is closed at which point the out-stream will be closed too.

func (Stream) EndsWith

func (s Stream) EndsWith(slice []Entry) bool

EndsWith returns true when this stream ends with the supplied elements.

func (Stream) Filter

func (s Stream) Filter(predicate Predicate) Stream

Filter returns a stream consisting of the elements of this stream that match the given predicate. This function streams continuously until the in-stream is closed at which point the out-stream will be closed too.

func (Stream) ForEach

func (s Stream) ForEach(consumer Consumer)

ForEach executes the given function for each entry in this stream. This is a continuous terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

func (Stream) GroupBy

func (s Stream) GroupBy(classifier Function) EntryMap

GroupBy groups the elements of this Stream by classifying them. This is a continuous terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

Example

ExampleStream_GroupBy shows a use of Stream's with GroupBy.

data := []ƒ.Entry{
	ƒ.Tuple2{E1: ƒ.EntryInt(1), E2: EntryString("one")},
	ƒ.Tuple2{E1: ƒ.EntryInt(2), E2: EntryString("two")},
	ƒ.Tuple2{E1: ƒ.EntryInt(3), E2: EntryString("three")},
	ƒ.Tuple2{E1: ƒ.EntryInt(4), E2: EntryString("four")},
	ƒ.Tuple2{E1: ƒ.EntryInt(5), E2: EntryString("five")},
	ƒ.Tuple2{E1: ƒ.EntryInt(6), E2: EntryString("six")},
	ƒ.Tuple2{E1: ƒ.EntryInt(7), E2: EntryString("seven")},
	ƒ.Tuple2{E1: ƒ.EntryInt(8), E2: EntryString("eight")},
	ƒ.Tuple2{E1: ƒ.EntryInt(9), E2: EntryString("nine")}}

resMap := map[ƒ.Entry]interface{}{}
ƒ.NewStreamFromSlice(data, 0).
	GroupBy(func(i ƒ.Entry) ƒ.Entry {
		return i.(ƒ.Tuple2).E1.(ƒ.EntryInt) & 1
	}).
	Stream(0).
	ForEach(func(e ƒ.Entry) {
		resMap[e.(ƒ.Tuple2).E1] = e.(ƒ.Tuple2).E2
	})

for i := 0; i < len(resMap); i++ {
	fmt.Printf("%d => %v\n", i, resMap[ƒ.EntryInt(i)])
}
Output:

0 => [{2 two} {4 four} {6 six} {8 eight}]
1 => [{1 one} {3 three} {5 five} {7 seven} {9 nine}]

func (Stream) Head

func (s Stream) Head() Entry

Head returns the first Entry in this stream.

func (Stream) HeadN

func (s Stream) HeadN(n uint64) []Entry

HeadN returns a slice of the first n elements in this stream.

func (Stream) Intersperse

func (s Stream) Intersperse(e Entry) Stream

Intersperse inserts an element between all elements of this Stream. This function streams continuously until the in-stream is closed at which point the out-stream will be closed too.

func (Stream) Last

func (s Stream) Last() Entry

Last returns the last Entry in this stream.

func (Stream) LastN

func (s Stream) LastN(n uint64) []Entry

LastN returns a slice of the last n elements in this stream.

func (Stream) LeftReduce

func (s Stream) LeftReduce(f2 BiFunction) Entry

LeftReduce accumulates the elements of this Stream by applying the given function. This is a continuous terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

func (Stream) Map

func (s Stream) Map(mapper Function) Stream

Map returns a slice of channel of Set consisting of the results of applying the given function to the elements of this stream. This function streams continuously until the in-stream is closed at which point the out-stream will be closed too.

func (Stream) MapToInt

func (s Stream) MapToInt(toInt ToIntFunction) IntStream

MapToInt produces an EntryInt stream. This function streams continuously until the in-stream is closed at which point the out-stream will be closed too.

func (Stream) NoneMatch

func (s Stream) NoneMatch(p Predicate) bool

NoneMatch returns whether none of the elements in the stream satisfies the predicate. It is the opposite of AnyMatch. This is a continuous terminal operation and hence expects the producer to close the stream in order to complete (or it will block).

func (Stream) Reduce

func (s Stream) Reduce(f2 BiFunction) Entry

Reduce is an alias for LeftReduce. See LeftReduce for more info.

func (Stream) StartsWith

func (s Stream) StartsWith(slice []Entry) bool

StartsWith returns true when this stream starts with the elements in the supplied slice.

func (Stream) Take

func (s Stream) Take(n uint64) Stream

Take returns a stream of the first 'n' elements of this stream. This function streams continuously until the 'n' elements are picked or the in-stream is closed at which point the out-stream will be closed too.

func (Stream) TakeUntil

func (s Stream) TakeUntil(p Predicate) Stream

TakeUntil returns a stream of the first elements of this stream until the predicate is satisfied. This function streams continuously until the in-stream is closed at which point the out-stream will be closed too.

func (Stream) TakeWhile

func (s Stream) TakeWhile(p Predicate) Stream

TakeWhile returns a stream of the first elements of this stream while the predicate is satisfied. This function streams continuously until the in-stream is closed at which point the out-stream will be closed too.

type ToIntFunction

type ToIntFunction func(e Entry) EntryInt

ToIntFunction that accepts one argument and produces an EntryInt result.

type Tuple

type Tuple interface {
	Entry
}

A Tuple is a container of value(s). A special case is Tuple0 which does not hold any value.

type Tuple0

type Tuple0 struct{}

Tuple0 is a tuple with 0 element.

func (Tuple0) Arity

func (t Tuple0) Arity() int

Arity is the number of elements in this tuple.

func (Tuple0) Equal

func (t Tuple0) Equal(o Entry) bool

Equal returns true if 'o' and 't' are equal.

func (Tuple0) Hash

func (t Tuple0) Hash() uint32

Hash returns the hash of this tuple.

func (Tuple0) ToSlice

func (t Tuple0) ToSlice() []Entry

ToSlice returns the elements of this tuple as a Go slice.

type Tuple1

type Tuple1 struct {
	E1 Entry
}

Tuple1 is a tuple with 1 element.

func (Tuple1) Arity

func (t Tuple1) Arity() int

Arity is the number of elements in this tuple.

func (Tuple1) Equal

func (t Tuple1) Equal(o Entry) bool

Equal returns true if 'o' and 't' are equal.

func (Tuple1) Hash

func (t Tuple1) Hash() uint32

Hash returns the hash of this tuple.

func (Tuple1) ToSlice

func (t Tuple1) ToSlice() []Entry

ToSlice returns the elements of this tuple as a Go slice.

type Tuple2

type Tuple2 struct {
	E1 Entry
	E2 Entry
}

Tuple2 is a tuple with 2 elements.

func (Tuple2) Arity

func (t Tuple2) Arity() int

Arity is the number of elements in this tuple.

func (Tuple2) Equal

func (t Tuple2) Equal(o Entry) bool

Equal returns true if 'o' and 't' are equal.

func (Tuple2) Hash

func (t Tuple2) Hash() uint32

Hash returns the hash of this tuple.

func (Tuple2) ToSlice

func (t Tuple2) ToSlice() []Entry

ToSlice returns the elements of this tuple as a Go slice.

Jump to

Keyboard shortcuts

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