seq

package module
v0.0.0-...-f04f80c Latest Latest
Warning

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

Go to latest
Published: Dec 19, 2023 License: 0BSD Imports: 6 Imported by: 26

README

Seq

GoDoc Build Status Coverage Status

Seq is a lazy sequence library for go. It is inspired by Clojure's sequence functions. It originally started because I was interested in transducers and wanted to play with them. Most of the functions in the library are implemeneted as transducers in the jsouthworth.net/go/transduce library and wrapped with a XfrmSequence here. This library relies heavily on reflection to allow for the most flexibility in what the user provides. This means that it is only type checked at runtime.

Getting started

go get jsouthworth.net/go/seq

Usage

The full documentation is available at jsouthworth.net/go/seq

License

This project is licensed under the 0BSD License - see LICENSE

Acknowledgments

  • Clojure's sequence library was the source of inspiration for the organization of this library and the names of the functions.

TODO

  • Implement a few more functions like flatten.
  • Add more conversions for go types (maps as entry sequences, etc.).

Documentation

Overview

Package seq is a lazy sequence library inspired by Clojure's sequence library. It uses transducers behind the scenes to implement the various functions. This provides a uniform mechanism for seperating the concept of a transformation from the mechanisms that perform that transformation.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Conj

func Conj(coll interface{}, elem interface{}) interface{}

Conj conjoins a new element into a collection returning the new collection.

func ConvertToString

func ConvertToString(coll Sequence) string

ConvertToString converts any Sequence to a string. This is useful for other sequence implementations that would like to use the same algorithm.

func DoRun

func DoRun(coll interface{})

DoRun will realize every element in a lazy sequence. coll is any type that can be converted to a Sequence by Seq.

func Every

func Every(pred interface{}, coll interface{}) bool

Every will iterate over every element of the sequence and return if the predicate hold for every element. pred must match the signature func(i iT) bool and will be called with reflection unless it is the non-specialized type func(interface{}) bool. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Every(func(x int) bool { return x == 10 }, Repeat(100, 10)))
Output:

true

func First

func First(coll interface{}) interface{}

First returns the first element of a sequence. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(First(RangeUntil(10)))
Output:

0

func Into

func Into(to interface{}, from interface{}) interface{}

Into takes an initial collection and a sequence and puts all the elements of the sequence into the collection returning the result.

func NotAny

func NotAny(pred interface{}, coll interface{}) bool

NotAny is the inverse of Some. pred must match the signature func(i iT) bool and will be called with reflection unless it is the non-specialized type func(interface{}) bool. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(NotAny(func(x int) bool { return x == 10 },
	Repeat(100, 10)))
Output:

false

func NotEvery

func NotEvery(pred interface{}, coll interface{}) bool

NotEvery is the inverse of Every. pred must match the signature func(i iT) bool and will be called with reflection unless it is the non-specialized type func(interface{}) bool. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(NotEvery(func(x int) bool { return x == 10 },
	Repeat(100, 10)))
Output:

false

func Reduce

func Reduce(
	fn interface{},
	init interface{},
	coll interface{},
) interface{}

Reduce takes a function and iterates over the sequence calling the function with the element at that place in the sequence and the result of the previous call. The initial result is provided as 'init' to the Reduce function. The reducing function 'fn' must match the signature func(result rT, input iT) rT and will be called using reflection unless is is the non-specialized type func(result, input interface{})interface{}. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Reduce(func(a, b int) int {
	return a + b
}, 0, RangeUntil(10)))
Output:

45

func Slice

func Slice(coll interface{}) []interface{}

Slice will convert a lazy sequence to a go slice realizing each element. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Slice(RangeUntil(10)))
Output:

[0 1 2 3 4 5 6 7 8 9]

func Some

func Some(pred interface{}, coll interface{}) bool

Some will return if pred is true for some element in the sequence. pred must match the signature func(i iT) bool and will be called with reflection unless it is the non-specialized type func(interface{}) bool. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Some(func(x int) bool { return x == 10 },
	Repeat(100, 10)))
Output:

true

func Transduce

func Transduce(
	xf transduce.Transducer,
	rf interface{},
	init interface{},
	coll interface{},
) interface{}

Transduce is a version of Reduce that takes a transducer and a reducing function and combines such that the transform is called on the elements being reduced. This is then passed to reduce to perform the actions greedily. The reducing function 'rf' must take both the result and the input type. That is, be of the type func(result rT, input eT) rT. This will be called using reflection unless it is the non-specialized func(result, input interface{})interface{}. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Transduce(
	transduce.Map(func(in int) int {
		return in + in
	}),
	func(result Sequence, input int) Sequence {
		return Cons(input, Seq(result))
	},
	Empty(),
	RangeUntil(10),
))
Output:

(18 16 14 12 10 8 6 4 2 0)

func TransformInto

func TransformInto(
	to interface{},
	xfrm transduce.Transducer,
	from interface{},
) interface{}

TransformInto takes an initial collection and a sequence and runs all the elements of the sequence through the transducer and places the results into the collection returning the result.

Types

type MapEntry

type MapEntry interface {
	Key() interface{}
	Value() interface{}
}

MapEntry is a key,value pair representing an item in a map when treated as a sequence.

type Seqable

type Seqable interface {
	Seq() Sequence
}

Seqable is any type that can return a sequence to iterate over its elements.

type Sequence

type Sequence interface {
	First() interface{}
	Next() Sequence
}

Sequence is any type that can return iterate down its elements.

func Concat

func Concat(colls ...interface{}) Sequence

Concat returns a lazy sequence that is the concatenation of the provided sequences. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Concat(Seq([]int{1, 2, 3}), Seq([]int{4, 5, 6})))
Output:

(1 2 3 4 5 6)

func Cons

func Cons(v interface{}, coll Sequence) Sequence

func Cycle

func Cycle(coll interface{}) Sequence

Cycle returns a lazy sequence consisting of the repeating the elements of coll. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Take(15, Cycle(RangeUntil(10))))
Output:

(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4)

func Dedupe

func Dedupe(coll interface{}) Sequence

Dedupe returns a lazy sequence with any duplicates removed. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Dedupe(Seq([]int{1, 1, 1, 2, 2, 3, 3, 3, 3})))
Output:

(1 2 3)

func DoAll

func DoAll(coll interface{}) Sequence

DoAll will realize every element in a lazy sequence and return that sequence. coll is any type that can be converted to a Sequence by Seq.

func Drop

func Drop(n int, coll interface{}) Sequence

Drop returns a lazy sequence that contains all but the first n elements in the passed in sequence. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Drop(10, RangeUntil(30)))
Output:

(10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29)

func DropWhile

func DropWhile(pred interface{}, coll interface{}) Sequence

DropWhile returns a lazy sequence of the items from the passed in sequence starting with the first element that for which pred returns false. pred must match the signature func(i iT) bool and will be called with reflection unless it is the non-specialized type func(interface{}) bool. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(DropWhile(func(x int) bool { return x < 9 },
	RangeUntil(20)))
Output:

(9 10 11 12 13 14 15 16 17 18 19)

func Empty

func Empty() Sequence

func Filter

func Filter(pred interface{}, coll interface{}) Sequence

Filter returns a lazy sequence that will contain the elements of the passed in sequence for which pred is true. pred must match the signature func(i iT) bool and will be called with reflection unless it is the non-specialized type func(interface{}) bool. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Filter(func(x int) bool { return x%2 == 0 },
	RangeUntil(10)))
Output:

(0 2 4 6 8)

func Interleave

func Interleave(colls ...interface{}) Sequence

Interleave returns a lazy sequence of the first element of each passed in sequence followed by the second, followed by the third, and so on. coll is any type that can be converted to a Sequence by Seq.

[coll[0][0], coll[1][0], ..., coll[n][0], ...,
 coll[0][m], coll[1[m], ..., coll[n][m]]
Example
s1 := []int{1, 2, 3, 4, 5, 6}
s2 := []int{7, 8, 9, 10, 11, 12}
s3 := []int{13, 14, 15, 16, 17, 18}
fmt.Println(Interleave(s1, s2, s3))
Output:

(1 7 13 2 8 14 3 9 15 4 10 16 5 11 17 6 12 18)

func Interpose

func Interpose(seperator interface{}, coll interface{}) Sequence

Interpose returns a lazy sequence of the elements of the passed in sequence seperated by the passed in seperator. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Interpose("\"-\"", RangeUntil(10)))
Output:

(0 "-" 1 "-" 2 "-" 3 "-" 4 "-" 5 "-" 6 "-" 7 "-" 8 "-" 9)

func Iterate

func Iterate(fn interface{}, x interface{}) Sequence

Iterate will return the result of calling fn on the result of the previous call of fn. The iteration starts with the passed in x.

Example
double := func(x int) int {
	return x + x
}
fmt.Println(Take(10, Iterate(double, 2)))
Output:

(2 4 8 16 32 64 128 256 512 1024)

func Keep

func Keep(f interface{}, coll interface{}) Sequence

Keep returns a lazy sequence for which f returns a non nil value The function f must be of the type func(i iT) oT and will be called with reflection unless it is the non-specialized type func(interface{}) interface{}. coll is any type that can be converted to a Sequence by Seq.

Example
ifOdd := func(in int) interface{} {
	if in%2 == 0 {
		return nil
	}
	return in
}
fmt.Println(Keep(ifOdd, RangeUntil(10)))
Output:

(1 3 5 7 9)

func KeepIndexed

func KeepIndexed(f interface{}, coll interface{}) Sequence

KeepIndexed returns a lazy sequence for which f returns a non nil value The function f must be of the type func(idx int, i iT) oT and will be called with reflection unless it is the non-specialized type func(int, interface{}) interface{}. coll is any type that can be converted to a Sequence by Seq.

Example
ifOdd := func(idx, in int) interface{} {
	if in%2 == 0 || idx > 4 {
		return nil
	}
	return in
}
fmt.Println(KeepIndexed(ifOdd, RangeUntil(10)))
Output:

(1 3)

func LazySeq

func LazySeq(fn func() Sequence) Sequence

func Map

func Map(fn interface{}, coll interface{}) Sequence

Map returns a lazy sqeuence that contains the result of applying fn to each item in the Sequence. The transforming function 'fn' must match the signature func(in iT) oT and will be called using reflection unless it us the non-specialized type func(interface{})interface{}. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Map(func(a int) int {
	return a + a
}, RangeUntil(10)))
Output:

(0 2 4 6 8 10 12 14 16 18)

func Mapcat

func Mapcat(f interface{}, colls ...interface{}) Sequence

Mapcat returns a lazy sequence that is the concatenation of the provided sequences modified by the mapping function f. f must be of the form func(in iT) oT and will be called with reflection unless it is the non-specialized func(interface{})interface{}. colls is an type that can be converted to a Sequence by Seq.

Example
fmt.Println(Mapcat(
	func(x Sequence) Sequence {
		return Remove(func(x int) bool {
			return x%2 == 0
		}, x)
	},
	Seq([]int{1, 2, 3}), Seq([]int{4, 5, 6}), Seq([]int{7, 8, 9})))
Output:

(1 3 5 7 9)

func Next

func Next(coll interface{}) Sequence

Next returns the sequence without the first element. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Next(RangeUntil(10)))
Output:

(1 2 3 4 5 6 7 8 9)

func PartitionAll

func PartitionAll(n int, coll interface{}) Sequence

PartitionAll returns a lazy sequence that consists of partitions of the provided sequence of n elements. If the length of the sequence is not a multiple of n then the remainder will be returned as the last element. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(PartitionAll(4,
	Seq([]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})))
Output:

((0 1 2 3) (4 5 6 7) (8 9))

func PartitionBy

func PartitionBy(f interface{}, coll interface{}) Sequence

PartitionBy returns a lazy sequence that consists of partitions of the provided sequence. The partitions are determined by f which is any function of type func(i iT) oT. When f returns a different value from its previous call then a parition is created. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(PartitionBy(func(x int) bool { return x%2 != 0 },
	Seq([]int{1, 1, 1, 2, 2, 3, 3})))
Output:

((1 1 1) (2 2) (3 3))

func Range

func Range(start, end, step int) Sequence

Range returns a lazy sequence that will be the integers [start, start+step, ..., end)

Example
fmt.Println(Range(1, 10, 2))
Output:

(1 3 5 7 9)

func RangeBetween

func RangeBetween(start, end int) Sequence

RangeBetween returns a lazy sequence that will be the integers [start,end).

Example
fmt.Println(RangeBetween(1, 5))
Output:

(1 2 3 4)

func RangeUntil

func RangeUntil(end int) Sequence

RangeUntil returns a lazy sequence that will be the integers [0,end).

Example
fmt.Println(RangeUntil(10))
Output:

(0 1 2 3 4 5 6 7 8 9)

func Remove

func Remove(pred interface{}, coll interface{}) Sequence

Filter returns a lazy sequence that will contain the elements of the passed in sequence for which pred is false. pred must match the signature func(i iT) bool and will be called with reflection unless it is the non-specialized type func(interface{}) bool. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Remove(func(x int) bool { return x%2 == 0 },
	RangeUntil(10)))
Output:

(1 3 5 7 9)

func Repeat

func Repeat(n int, x interface{}) Sequence

Repeat will return a lazy sequence that repeats x, n times.

Example
fmt.Println(Repeat(10, "foo"))
Output:

(foo foo foo foo foo foo foo foo foo foo)

func RepeateInfinitely

func RepeateInfinitely(x interface{}) Sequence

RepeatInfinitely will return a lazy sequence that repeats x forever.

func Replace

func Replace(smap interface{}, coll interface{}) Sequence

Replace returns a lazy sequence that contains the result of replacing the values in the provided smap for the ones in the sequence. smap must be one of the following types something that implements interface { Find(interface{}) (interface{},bool) }, map[iT]oT. Reflection is used unless the map is of the non specialized map[interface{}]interface{} type. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Replace(map[int]int{
	1: 10,
}, RangeUntil(10)))
Output:

(0 10 2 3 4 5 6 7 8 9)

func Seq

func Seq(coll interface{}) Sequence

Seq will convert a type to a sequence. If the type is Sequable it will run Seq(), if it is already a sequence it will return the sequence, otherwise it will attempt to build a sequence using reflection. Currently it supports automatic conversion of both arbitray go slices ([]T) and strings.

func SplitAt

func SplitAt(index int, coll interface{}) Sequence

SplitAt returns a sequence containing two sequences corresponding to the split index. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(SplitAt(9, RangeUntil(20)))
Output:

((0 1 2 3 4 5 6 7 8) (9 10 11 12 13 14 15 16 17 18 19))

func SplitWith

func SplitWith(pred interface{}, coll interface{}) Sequence

SplitWith returns a sequence containing two sequences corresponding to predicate. pred must match the signature func(i iT) bool and will be called with reflection unless it is the non-specialized type func(interface{}) bool. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(SplitWith(func(x int) bool { return x < 9 },
	RangeUntil(20)))
Output:

((0 1 2 3 4 5 6 7 8) (9 10 11 12 13 14 15 16 17 18 19))

func Take

func Take(n int, coll interface{}) Sequence

Take will return a lazy but finite sequence consisting of the first n elements of the passed in sequence. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(Take(10, RangeUntil(30)))
Output:

(0 1 2 3 4 5 6 7 8 9)

func TakeNth

func TakeNth(n int, coll interface{}) Sequence

TakeNth will return a lazy sequence consisting of every nth item of the passed in collection. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(TakeNth(4, RangeUntil(30)))
Output:

(3 7 11 15 19 23 27)

func TakeWhile

func TakeWhile(pred interface{}, coll interface{}) Sequence

TakeWhile returns a lazy sequence of the items from the passed in sequence so long as pred returns true. pred must match the signature func(i iT) bool and will be called with reflection unless it is the non-specialized type func(interface{}) bool. coll is any type that can be converted to a Sequence by Seq.

Example
fmt.Println(TakeWhile(func(x int) bool { return x < 9 },
	RangeUntil(20)))
Output:

(0 1 2 3 4 5 6 7 8)

func XfrmSequence

func XfrmSequence(xf transduce.Transducer, coll Sequence) Sequence

XfrmSequence returns a lazy sequence that is the result of stepping the transducer over the elements of the passed in sequence. The resulting sequence may be longer or shorter than the original sequence based on the results of the transducer.

Example
xform := transduce.Compose(
	transduce.Map(func(x int) int {
		return x + 1
	}),
	transduce.Filter(func(x int) bool {
		return x%2 == 0
	}),
	transduce.Dedupe(),
	transduce.Mapcat(Reduce, RangeUntil),
	transduce.PartitionAll(3),
	transduce.PartitionBy(func(coll interface{}) bool {
		return Reduce(func(res, x int) int { return res + x },
			0, coll).(int) > 7
	}),
	transduce.Cat(Reduce), //TODO: implement flatten and combine
	transduce.Cat(Reduce), //TODO: implement flatten and combine
	transduce.RandomSample(1.0),
	transduce.TakeNth(1),
	transduce.Keep(func(x int) interface{} {
		if x%2 != 0 {
			return x * x
		}
		return nil
	}),
	transduce.KeepIndexed(func(i, x int) interface{} {
		if i%2 == 0 {
			return i * x
		}
		return nil
	}),
	transduce.Replace(map[int]string{
		2:  "two",
		6:  "six",
		18: "eighteen",
	}),
	transduce.Take(11),
	transduce.TakeWhile(func(x interface{}) bool {
		return x != 300
	}),
	transduce.Drop(1),
	transduce.DropWhile(func(x interface{}) bool {
		_, isString := x.(string)
		return isString
	}),
	transduce.Remove(func(x interface{}) bool {
		_, isString := x.(string)
		return isString
	}),
)
data := Interleave(RangeUntil(18), RangeUntil(20))
fmt.Println(XfrmSequence(xform, data))
Output:

(36 200 10)

Jump to

Keyboard shortcuts

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