Last active
April 15, 2024 17:55
-
-
Save marz619/6bbbbe0323899a6cc4b59ea30bbaadef to your computer and use it in GitHub Desktop.
Composition & Higher-Order Functions in Golang (via: https://faiface.github.io/post/how-i-built-audio-lib-composite-pattern/)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fun | |
// bufferedSequence | |
type bufferedSeq struct { | |
seq Seq // original Seq | |
buf *[]float64 // shared slice | |
pos int // this pos | |
} | |
// Next implements Seq interface | |
func (bs *bufferedSeq) Next() (float64, bool) { | |
// need new elem from sequence | |
if bs.pos >= len(*bs.buf) { | |
v, ok := bs.seq.Next() | |
if !ok { | |
return v, ok | |
} | |
*bs.buf = append(*bs.buf, v) | |
} | |
// otherwise buffer has advanced | |
v := (*bs.buf)[bs.pos] | |
bs.pos++ | |
return v, true | |
} | |
func bufferedSeqs(n int, seq Seq) []Seq { | |
buf := make([]float64, 0) | |
bufSeqs := make([]Seq, n) | |
for i := range bufSeqs { | |
bufSeqs[i] = newBufferedSeq(seq, &buf) | |
} | |
return bufSeqs | |
} | |
func newBufferedSeq(seq Seq, buf *[]float64) Seq { | |
return &bufferedSeq{seq: seq, buf: buf} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fun | |
// Expr is a function type that yields a float64 | |
// i.e. an Expression of float64 | |
type Expr func() float64 | |
// Const returns an Expr that always yields x | |
func Const(c float64) Expr { | |
return func() float64 { | |
return c | |
} | |
} | |
// Ref returns an Expr that yields the value of x | |
func Ref(r *float64) Expr { | |
return func() float64 { | |
return *r | |
} | |
} | |
// Sum returns an Expr that will yield the sum | |
// of the provided expressions | |
func Sum(exprs ...Expr) Expr { | |
return func() float64 { | |
sum := 0.0 | |
for _, ex := range exprs { | |
sum += ex() | |
} | |
return sum | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fun | |
// Seq is a sequence interface | |
type Seq interface { | |
Next() (float64, bool) | |
} | |
// SeqFunc implements the Seq interface | |
type SeqFunc func() (float64, bool) | |
// Next returns the value generated by the SeqFunc | |
func (sf SeqFunc) Next() (float64, bool) { | |
return sf() | |
} | |
// Make returns a Seq from a series of values | |
func Make(vals ...float64) Seq { | |
// index tracker | |
i := 0 | |
// our func | |
sf := func() (float64, bool) { | |
if i >= len(vals) { | |
return 0, false | |
} | |
x := vals[i] | |
i++ | |
return x, true | |
} | |
return SeqFunc(sf) | |
} | |
// Collect the values of a Seq and return it as a slice | |
func Collect(seq Seq, hint ...int) []float64 { | |
var vals []float64 | |
if len(hint) > 0 && hint[0] > 0 { | |
vals = make([]float64, 0, hint[0]) | |
} | |
for { | |
if v, ok := seq.Next(); ok { | |
vals = append(vals, v) | |
continue | |
} | |
break | |
} | |
return vals | |
} | |
// Take n items from a Seq | |
func Take(n int, seq Seq) Seq { | |
sf := func() (float64, bool) { | |
if n <= 0 { | |
return 0, false | |
} | |
n-- | |
return seq.Next() | |
} | |
return SeqFunc(sf) | |
} | |
// Split a Seq at some index n | |
func Split(n int, seq Seq) (Seq, Seq) { | |
return Make(Collect(Take(n, seq))...), seq | |
} | |
// Dup returns two Seqs identical to the provided Seq | |
// | |
// This assumes the original Seq will not be pre-emptively | |
// consumed. Additionally, this is not safe for concurrent | |
// use. | |
func Dup(seq Seq) (Seq, Seq) { | |
dup := bufferedSeqs(2, seq) | |
return dup[0], dup[1] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package fun | |
// Naturals is the infinite series of natural numbers | |
func Naturals() Seq { | |
n := 0.0 | |
sf := func() (float64, bool) { | |
n++ | |
return n, true | |
} | |
return SeqFunc(sf) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment