fuego

package module
v10.0.0 Latest Latest
Warning

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

Go to latest
Published: Nov 11, 2020 License: Apache-2.0 Imports: 7 Imported by: 0

README

ƒuego logo

ƒuego - Functional Experiment in Go

Tweet

fuego goreportcard

Buy Me A Coffee

ƒuego example

ƒuego example

Table of content

Overview

Making Go come to functional programming.

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

ƒuego 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.

I hope you will find it useful!

Have fun!!

(toc)

Documentation

The code documentation and some examples can be found on godoc.

The tests form the best source of documentation. ƒuego 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:
Most tests use unbuffered channels to help detect deadlocks. In real life scenarios, it is recommended to use buffered channels for increased performance.

(toc)

Installation

Download

go get github.com/seborama/fuego

Or for a specific version:

go get gopkg.in/seborama/fuego.v8

Import in your code

You can import the package in the usual Go fashion.

To simplify usage, you can use an alias:

package sample

import ƒ "gopkg.in/seborama/fuego.v8"

...or import as an unqualified dot import:

package sample

import . "gopkg.in/seborama/fuego.v8"

(toc)

Example Stream

    strs := EntrySlice{
        EntryString("a"),
        EntryString("bb"),
        EntryString("cc"),
        EntryString("ddd"),
    }
    
    NewStreamFromSlice(strs, 500).
        Filter(isEntryString).
        Distinct().
        Collect(
            GroupingBy(
                stringLength,
                Mapping(
                    stringToUpper,
                    Filtering(
                        stringLengthGreaterThan(1),
                        ToEntrySlice()))))
    }

    // result: map[1:[] 2:[BB CC] 3:[DDD]]

(toc)

Contributions

Contributions and feedback are welcome.

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

If you have an idea to improve ƒuego, please share it via an issue. And if you like ƒuego give it a star to show your support for the project - it will put a smile on my face! 😊

Thanks!!

(toc)

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 ƒuego 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.

(toc)

Pressure

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

When the buffer of a Stream's channel of a consumer 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.

(toc)

Concept: 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 theEntry interface. This provides an abstraction of types yet with known behaviour:

  • Hash(): identifies an Entry Uniquely.
  • Equal(): defines equality for a concrete type of Entry. Equal() is expected to be based on Hash() for non-basic types. Equal should ensure the compared Entry is of the same type as the reference Entry. For instance, EntryBool(false) and EntryInt(0) both have a Hash of 0, yet they aren't equal.

Several Entry implementations are provided:

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

Check the godoc for additional methods each of these may provide.

(toc)

Features summary

Streams:

  • Stream
  • IntStream
  • FloatStream
  • CStream - concurrent implementation of Stream

Functional Types:

  • Maybe
  • Tuple
  • Predicate:
    • True
    • False
    • FunctionPredicate

Functions:

  • Consumer
  • Function:
    • ToIntFunction
    • ToFloatFunction
  • BiFunction
  • StreamFunction:
    • FlattenEntrySliceToEntry
  • Predicate:
    • Or
    • Xor
    • And
    • Not / Negate

Collectors:

  • GroupingBy
  • Mapping
  • FlatMapping
  • Filtering
  • Reducing
  • ToEntrySlice
  • ToEntryMap
  • ToEntryMapWithKeyMerge

Check the godoc for full details.

(toc)

Concurrency

As of v8.0.0, a new concurrent model offers to process a stream concurrently while preserving order.

This is not possible yet with all Stream methods but is available with e.g. Stream.Map.

Notes on concurrency

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 ƒuego streams can be created and data distributed across as desired. This empowers users of ƒuego to implement the desired behaviour of their pipelines.

Stream has some methods that fan out (e.g. ForEachC). See the godoc for further information and limitations.

I recommend Rob Pike's slides on Go concurrency patterns:

As a proof of concept and for facilitation, ƒuego has a CStream implementation to manage concurrently a collection of Streams.

(toc)

Collectors

A Collector is a mutable reduction operation, optionally transforming the accumulated result.

Collectors can be combined to express complex operations in a concise manner.
Simply put, a collector allows creating custom actions on a Stream.

ƒuego exposes a number of functional methods such as MapToInt, Head, LastN, Filter, etc...
Collectors also provide a few functional methods.

But... what if you need something else? And it is not straighforward or readable when combining the existing methods ƒuego offers?

Enters Collector: implement you own requirement functionally!
Focus on what needs doing in your streams (and delegate the details of the how to the implementation of your Collector).

(toc)

Known limitations

  • several operations may be memory intensive or poorly performing.

(toc)

Buy Me A Coffee

Documentation

Overview

Package fuego is a FUnctional Experiment in GO. This is a research project for functional constructs in Go. This is a research project. Seb C.

Index

Examples

Constants

View Source
const (
	// PanicDuplicateKey signifies that the key already exists for this map.
	PanicDuplicateKey = "duplicate key"
)
View Source
const PanicInvalidConcurrencyLevel = "stream concurrency must be at least 0"

PanicInvalidConcurrencyLevel signifies that the Stream is missing a channel.

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 EntriesEqual

func EntriesEqual(e1, e2 Entry) bool

EntriesEqual checks the equality of 2 Entry objects. Note: EntriesEqual(&entry1, &entry2) will not produce the desired outcome with this method.

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 BiConsumer

type BiConsumer func(i, j Entry)

BiConsumer that accepts two arguments and does not return any value.

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 CStream

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

CStream is a concurrent stream.

func NewCStream

func NewCStream(channels []chan Entry) CStream

NewCStream creates a new concurrent stream.

func (CStream) AddStreamFromChannels

func (cs CStream) AddStreamFromChannels(channels []chan Entry) CStream

AddStreamFromChannels adds Streams derived from the supplied channels to this CStream.

func (CStream) AddStreamFromSlices

func (cs CStream) AddStreamFromSlices(slices []EntrySlice, bufsize int) CStream

AddStreamFromSlices adds Streams derived from the supplied slices to this CStream.

func (CStream) AddStreams

func (cs CStream) AddStreams(streams []Stream) CStream

AddStreams adds Streams to this CStream.

func (CStream) Filter

func (cs CStream) Filter(predicate Predicate) CStream

Filter is the concurrent equivalent of Stream.Filter. See Stream.Filter for further information.

func (CStream) ForEach

func (cs CStream) ForEach(consumer Consumer)

ForEach is the concurrent equivalent of Stream.ForEach. See Stream.ForEach for further information.

type Collector

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

A Collector is a mutable reduction operation, optionally transforming the accumulated result.

Collectors can be combined to express complex operations in a concise manner.

In other words, a collector allows creating custom actions on a Stream. **fuego** comes shipped with a number of methods such as `MapToInt`, `Head`, `LastN`, `Filter`, etc, and Collectors also provide a few additional methods. But what if you need something else? And it is straighforward or readable when combining the existing methods fuego offers? Enters `Collector`: implement you own requirement functionally! Focus on *what* needs to be done in your streams (and delegate the details of the *how* to the implementation of your `Collector`).

It should be noted that the `finisher` function is optional (i.e. it may acceptably be `nil`).

Example:

strs := EntrySlice{
    EntryString("a"),
    EntryString("bb"),
    EntryString("cc"),
    EntryString("ddd"),
}

NewStreamFromSlice(strs, 1e3).
    Collect(
        GroupingBy(
            stringLength,
            Mapping(
                stringToUpper,
                ToEntryMap())))
// Result: map[1:[A] 2:[BB CC] 3:[DDD]]

func Filtering

func Filtering(predicate Predicate, collector Collector) Collector

Filtering adapts the Entries a Collector accepts to a subset that satisfies the given predicate.

func FlatMapping

func FlatMapping(mapper StreamFunction, collector Collector) Collector

FlatMapping adapts the Entries a Collector accepts to another type by applying a flat mapping function which maps input elements to a `Stream`.

func GroupingBy

func GroupingBy(classifier Function, downstream Collector) Collector

GroupingBy groups the elements of the downstream Collector by classifying them with the provided classifier function.

func Mapping

func Mapping(mapper Function, collector Collector) Collector

Mapping adapts the Entries a Collector accepts to another type.

func NewCollector

func NewCollector(supplier Supplier, accumulator BiFunction, finisher Function) Collector

NewCollector creates a new Collector.

func Reducing

func Reducing(f2 BiFunction) Collector

Reducing returns a collector that performs a reduction of its input elements using the provided BiFunction.

func ToEntryMap

func ToEntryMap(keyMapper, valueMapper Function) Collector

ToEntryMap returns a collector that accumulates the input entries into an EntryMap.

func ToEntryMapWithKeyMerge

func ToEntryMapWithKeyMerge(keyMapper, valueMapper Function, mergeFunction BiFunction) Collector

ToEntryMapWithKeyMerge returns a collector that accumulates the input entries into an EntryMap. Duplicate keys are managed by mergeFunction. See EntryMap.Merge() for details about the mergeFunction.

func ToEntrySlice

func ToEntrySlice() Collector

ToEntrySlice returns a collector that accumulates the input entries into an EntrySlice.

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.

func IdentityFinisher

func IdentityFinisher(e Entry) Entry

IdentityFinisher is a basic finisher that returns the original value passed to it, unmodified.

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 EntryByte

type EntryByte byte

EntryByte is an Entry for 'byte'.

func (EntryByte) Equal

func (i EntryByte) Equal(e Entry) bool

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

func (EntryByte) Hash

func (i EntryByte) Hash() uint32

Hash returns a hash for 'i'.

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]Entry

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

func (EntryMap) Equal

func (em EntryMap) Equal(e Entry) bool

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

func (EntryMap) HasKey

func (em EntryMap) HasKey(key Entry) bool

HasKey returns true if this map has the supplied key.

func (EntryMap) Hash

func (em EntryMap) Hash() uint32

Hash returns a hash for this Entry.

func (EntryMap) Len

func (em EntryMap) Len() int

Len returns the number of Entries in this EntryMap.

func (EntryMap) Merge

func (em EntryMap) Merge(key, value Entry, mergeFunction BiFunction) EntryMap

Merge performs a value merge on the specified key in this EntryMap. If the supplied key does not exist in this EntryMap, the supplied value is assigned. If the supplied key already exists, mergeFunction is called to determine the new value that will replace the current.

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) Append

func (es EntrySlice) Append(e Entry) EntrySlice

Append an Entry to this EntrySlice.

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.

func (EntrySlice) Len

func (es EntrySlice) Len() int

Len returns the number of Entries in this EntrySlice.

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 transforms this EntryString to lower case.

func (EntryString) MapToEntryBytes

func (es EntryString) MapToEntryBytes(bufsize int) Stream

MapToEntryBytes transforms the bytes of this EntryString to a Stream of EntryBytes.

func (EntryString) ToLower

func (es EntryString) ToLower() EntryString

ToLower transforms this EntryString to lower case.

func (EntryString) ToUpper

func (es EntryString) ToUpper() EntryString

ToUpper transforms this EntryString to upper case.

type FloatStream

type FloatStream struct {
	Stream
}

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

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`).

func NewConcurrentFloatStream

func NewConcurrentFloatStream(c chan EntryFloat, n int) FloatStream

NewConcurrentFloatStream creates a new FloatStream with a degree of concurrency of n. This function leaves the provided channel is the same state of openness.

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 IntStream

type IntStream struct {
	Stream
}

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

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`).

func NewConcurrentIntStream

func NewConcurrentIntStream(c chan EntryInt, n int) IntStream

NewConcurrentIntStream creates a new IntStream with a degree of concurrency of n. This function leaves the provided channel is the same state of openness.

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) Filter

func (m Maybe) Filter(predicate Predicate) Maybe

Filter returns MaybeSome(value) if this is a MaybeSome and the value satisfies the predicate otherwise returns MaybeNone.

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(elseEntry 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(elseMaybe 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/v10"
)

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.

A Stream is a wrapper over a Go channel ('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.

As of v8.0.0, fuego offers ordered concurrency for some linear operations such as Map().

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.

Example:

ƒ.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)

func NewConcurrentStream

func NewConcurrentStream(c chan Entry, n int) Stream

NewConcurrentStream creates a new Stream with a degree of concurrency of n.

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 EntrySlice, 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).

Example:

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

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).

Example:

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

func (Stream) Collect

func (s Stream) Collect(c Collector) interface{}

Collect reduces and optionally mutates the stream with the supplied Collector.

It should be noted that this method returns an `interface{}` which enables it to return `Entry` as well as any other Go types.

Also, the `finisher` function is optional. (i.e. it may acceptably be `nil`).

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

Example:

strs := EntrySlice{
	EntryString("a"),
	EntryString("bb"),
	EntryString("cc"),
	EntryString("ddd"),
}

NewStreamFromSlice(strs, 1e3).
    Collect(
        GroupingBy(
            stringLength,
            Mapping(
                stringToUpper,
                Filtering(
                    stringLengthGreaterThan(1),
                    ToEntrySlice()))))
// Result: map[1:[] 2:[BB CC] 3:[DDD]]

func (Stream) Concurrent

func (s Stream) Concurrent(n int) Stream

Concurrent sets the level of concurrency for this Stream.

This is used for concurrent methods such as Stream.Map.

Consumption is ordered by the stream's channel but output may be unordered (a slow consumer will be "out-raced" by faster consumers). Ordering is dependent on the implementation of concurrency. For instance Stream.Map() is orderly but Stream.ForEachC is not.

Note that to switch off concurrency, you should provide n = 0. With n = 1, concurrency is internal whereby the Stream writer will not block on writing a single element (i.e. buffered channel of 1). This already provides significant processing gains.

Performance:

Channels are inherently expensive to use owing to their internal mutex lock.

Benefits will ONLY be observed when the execution has a degree of latency (at the very least, several dozens of nanoseconds). The higher the latency, the better the gains from concurrency (even on a single CPU core).

If latency is too low or next to none, using concurrency will likely be slower than without, particularly when no CPU core is available.

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) Distinct

func (s Stream) Distinct() Stream

Distinct returns a stream of the distinct elements of this stream.

This operation is costly both in time and in memory. It is strongly recommended to use buffered channels for this operation.

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

func (Stream) Drop

func (s Stream) Drop(n uint64) Stream

Drop the first 'n' elements of this stream 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.

Example:

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

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.

Example:

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

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.

Example:

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

func (Stream) EndsWith

func (s Stream) EndsWith(slice EntrySlice) bool

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

This is a potentially expensive method since it has to consume all the elements in the Stream.

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

Example:

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

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.

Example:

s := ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryInt(1),
    ƒ.EntryInt(2),
    ƒ.EntryInt(3),
}, 0)

s.Filter(
        FunctionPredicate(entryIntEqualsTo(ƒ.EntryInt(1))).
            Or(
                FunctionPredicate(entryIntEqualsTo(ƒ.EntryInt(3)))),
)
// Result: []ƒ.EntryInt{1,3}

func (Stream) FlatMap

func (s Stream) FlatMap(mapper StreamFunction) Stream

FlatMap takes a StreamFunction to flatten the entries in this stream and produce a new stream.

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

See: example_stream_test.go.

Example
a := EntrySlice{EntryInt(1), EntryInt(2), EntryInt(3)}
b := EntrySlice{EntryInt(4), EntryInt(5)}
c := EntrySlice{EntryInt(6), EntryInt(7), EntryInt(8)}

sliceOfEntrySlicesOfEntryInts := EntrySlice{a, b, c}

fmt.Printf("Before flattening: %+v\n", sliceOfEntrySlicesOfEntryInts)

sliceOfEntryInts := NewStreamFromSlice(sliceOfEntrySlicesOfEntryInts, 0).
	FlatMap(FlattenEntrySliceToEntry(0)).
	Collect(ToEntrySlice())

fmt.Printf("After flattening: %+v\n", sliceOfEntryInts)
Output:

Before flattening: [[1 2 3] [4 5] [6 7 8]]
After flattening: [1 2 3 4 5 6 7 8]

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).

Example:

total := 0

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

s := ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryInt(1),
    ƒ.EntryInt(2),
    ƒ.EntryInt(3),
}, 0).
    ForEach(calculateSumTotal)
// Result: total == 6

func (Stream) ForEachC

func (s Stream) ForEachC(consumer Consumer)

ForEachC is a concurrent wrapper of ForEach.

The level of concurrency is set by the last call made to method Concurrent.

See 'ForEach' for full details.

Note that this method consumes the stream orderly but does NOT preserve order of output.

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).

See: example_stream_test.go.

Example

ExampleStream_GroupBy shows a use of Stream's with GroupBy.

data := EntrySlice{
	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.

This function only consumes at most one element from the stream.

Example:

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

func (Stream) HeadN

func (s Stream) HeadN(n uint64) EntrySlice

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

This function only consumes at most 'n' elements from the stream.

Example:

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

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.

Example:

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("three"),
    ƒ.EntryString("two"),
    ƒ.EntryString("four"),
}, 1e3).
    Intersperse(ƒ.EntryString(" - "))
// Result: "three - two - four"

func (Stream) Last

func (s Stream) Last() Entry

Last returns the last Entry in this stream.

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

Example:

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

func (Stream) LastN

func (s Stream) LastN(n uint64) EntrySlice

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

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

Example:

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

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).

Example:

ƒ.NewStreamFromSlice([]ƒ.Entry{
    ƒ.EntryString("four"),
    ƒ.EntryString("twelve)",
    ƒ.EntryString("one"),
    ƒ.EntryString("six"),
    ƒ.EntryString("three"),
}, 1e3).
    Reduce(concatenateStringsBiFunc)
// Result: ƒ.EntryString("four-twelve-one-six-three")

func (Stream) Limit

func (s Stream) Limit(n uint64) Stream

Limit is a synonym for Take.

func (Stream) Map

func (s Stream) Map(mapper Function) Stream

Map returns a Stream consisting of the result 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) MapToFloat

func (s Stream) MapToFloat(toFloat ToFloatFunction) FloatStream

MapToFloat produces an EntryFloat 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).

Example:

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

func (Stream) Peek

func (s Stream) Peek(consumer Consumer) Stream

Peek is akin to ForEach but returns the Stream.

This is useful e.g. for debugging.

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

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 EntrySlice) bool

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

This function only consume as much data from the stream as is necessary to prove (or disprove) it starts with the supplied slice data.

Example:

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

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.

Example:

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

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.

Example:

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

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.

Example:

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

func (Stream) ToSlice

func (s Stream) ToSlice() EntrySlice

ToSlice extracts the elements of the stream into an EntrySlice.

This is a special case of a reduction.

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

type StreamFunction

type StreamFunction func(e Entry) Stream

StreamFunction that accepts one argument and produces a stream.

It is worth noting is `StreamFunction` which accepts one argument

and produces a stream. It is used with when "flat mapping" and

`Stream`. This effectively is a one to many operation, such as exploding the individual values of an EntrySlice into a Stream.

This effectively is a one to many operation, such as exploding the individual values of an EntrySlice into a Stream.

func FlattenEntrySliceToEntry

func FlattenEntrySliceToEntry(bufsize int) StreamFunction

FlattenEntrySliceToEntry is a StreamFunction that flattens an EntrySlice to a Stream of its elements.

type Supplier

type Supplier func() Entry

Supplier accepts no argument and returns an Entry.

type ToFloatFunction

type ToFloatFunction func(e Entry) EntryFloat

ToFloatFunction that accepts one argument and produces an EntryFloat result.

type ToIntFunction

type ToIntFunction func(e Entry) EntryInt

ToIntFunction that accepts one argument and produces an EntryInt result.

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() EntrySlice

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) Map

func (t Tuple1) Map(mapper Function) Tuple1

Map applies the supplied mapper to the element of this Tuple and returns a new Tuple.

func (Tuple1) MapMulti

func (t Tuple1) MapMulti(mapper1 Function) Tuple1

MapMulti applies the supplied mappers one for each element of this Tuple and returns a new Tuple.

func (Tuple1) ToSlice

func (t Tuple1) ToSlice() EntrySlice

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) Map

func (t Tuple2) Map(mapper Function) Tuple2

Map applies the supplied mapper to all elements of this Tuple and returns a new Tuple.

func (Tuple2) MapMulti

func (t Tuple2) MapMulti(mapper1 Function, mapper2 Function) Tuple2

MapMulti applies the supplied mappers one for each element of this Tuple and returns a new Tuple.

func (Tuple2) ToSlice

func (t Tuple2) ToSlice() EntrySlice

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

type Tuple3

type Tuple3 struct {
	E1 Entry
	E2 Entry
	E3 Entry
}

Tuple3 is a tuple with 3 elements.

func (Tuple3) Arity

func (t Tuple3) Arity() int

Arity is the number of elements in this tuple.

func (Tuple3) Equal

func (t Tuple3) Equal(o Entry) bool

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

func (Tuple3) Hash

func (t Tuple3) Hash() uint32

Hash returns the hash of this tuple.

func (Tuple3) Map

func (t Tuple3) Map(mapper Function) Tuple3

Map applies the supplied mapper to all elements of this Tuple and returns a new Tuple.

func (Tuple3) MapMulti

func (t Tuple3) MapMulti(mapper1 Function, mapper2 Function, mapper3 Function) Tuple3

MapMulti applies the supplied mappers one for each element of this Tuple and returns a new Tuple.

func (Tuple3) ToSlice

func (t Tuple3) ToSlice() EntrySlice

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