Skip to content

Instantly share code, notes, and snippets.

@ninedraft
Last active March 31, 2021 14:53
Show Gist options
  • Save ninedraft/022f0978065a4174a33a7483a0c16794 to your computer and use it in GitHub Desktop.
Save ninedraft/022f0978065a4174a33a7483a0c16794 to your computer and use it in GitHub Desktop.
Go2 std
func Await[C context.Context, E any](ctx C, ch <-chan E) (E, bool) {
select {
case <-ctx.Done():
var empty E
return empty, false
case v, ok := <-ch:
return v, ok
}
}
type BatchFormer[T any] struct {
maxSize uint
buf []T
consumer func([]T) error
}
func NewBatchFormer[T any](max uint, consumer func([]T) error) *BatchFormer[T] {
if consumer == nil {
panic("BatchFormer: consumer must be not nil")
}
return &BatchFormer[T]{
maxSize: max,
buf: make([]T, 0, max),
consumer: consumer,
}
}
func (bf *BatchFormer[T]) Push(v T) error {
bf.buf = append(bf.buf, v)
if uint(len(bf.buf)) < bf.maxSize {
return nil
}
return bf.Flush()
}
func (bf *BatchFormer[T]) Seep(ctx context.Context, ch <-chan T) error {
for {
var v, ok = Await(ctx, ch)
if !ok {
return nil
}
var err = bf.Push(v)
if err != nil {
return err
}
}
}
func (bf *BatchFormer[T]) Flush() error {
defer bf.reset()
if len(bf.buf) == 0 {
return nil
}
return bf.consumer(bf.buf)
}
func (bf *BatchFormer[T]) reset() {
var void T
for i := range bf.buf {
bf.buf[i] = void
}
bf.buf = bf.buf[:0]
}
type Task[T any] func(ctx context.Context, x T) error
func Distribute[T any](ctx context.Context, x T, tasks ...Task[T]) error {
var wg = &sync.WaitGroup{}
wg.Add(len(tasks))
ctx, cancel := context.WithCancel(ctx)
defer cancel()
var joiner = &errorJoiner{}
for _, task := range tasks {
task := task
go func() {
defer wg.Done()
joiner.Push(task(ctx, x))
}()
}
wg.Wait()
return nil
}
type errorJoiner struct {
mu sync.Mutex
err error
}
func (ej *errorJoiner) Push(err error) {
if err == nil {
return
}
ej.mu.Lock()
defer ej.mu.Unlock()
ej.err = err
}
func (ej *errorJoiner) Err() error {
ej.mu.Lock()
defer ej.mu.Unlock()
return ej.err
}
type HashSet[E comparable] map[E]struct{}
func From[E comparable](items ...E) HashSet[E] {
var set = make(HashSet[E], len(items))
for _, item := range items {
set[item] = struct{}{}
}
return set
}
func FromItems[E comparable](items []E) HashSet[E] {
var set = make(HashSet[E], len(items))
for _, item := range items {
set[item] = struct{}{}
}
return set
}
func FromIter[E comparable](n int, next func(i int) (E, bool)) HashSet[E] {
var preallocate = n
if preallocate <= 0 {
preallocate = 16
}
var set = make(HashSet[E], preallocate)
for i := 0; i < n || n < 0; i++ {
var item, ok = next(i)
if !ok {
break
}
set[item] = struct{}{}
}
return set
}
func (set HashSet[E]) Len() int { return len(set) }
func (set HashSet[E]) Add(item E) {
set[item] = struct{}{}
}
func (set HashSet[E]) AddItems(items []E) {
for _, item := range items {
set.Add(item)
}
}
func (set HashSet[E]) Contains(item E) bool {
var _, ok = set[item]
return ok
}
func (set HashSet[E]) Delete(item E) bool {
if set.Contains(item) {
delete(set, item)
return true
}
return false
}
func (set HashSet[E]) Clone() HashSet[E] {
var c = make(HashSet[E], set.Len())
for item := range set {
c.Add(item)
}
return c
}
func (set HashSet[E]) Items() []E {
var items = make([]E, 0, set.Len())
for item := range set {
items = append(items, item)
}
return items
}
func (set HashSet[E]) Equal(other HashSet[E]) bool {
if set.Len() != other.Len() {
return false
}
for item := range set {
if !other.Contains(item) {
return false
}
}
return true
}
func (set HashSet[E]) Intersect(other HashSet[E]) {
for item := range set {
if !other.Contains(item) {
delete(set, item)
}
}
}
func (set HashSet[E]) Sub(other HashSet[E]) {
for item := range other {
delete(set, item)
}
}
func (set HashSet[E]) SubItems(items []E) {
for _, item := range items {
delete(set, item)
}
}
func (set HashSet[E]) Filter(predicate func(E) bool) HashSet[E] {
var n int
for item := range set {
if predicate(item) {
n++
}
}
var result = make(HashSet[E], n)
for item := range set {
if predicate(item) {
result[item] = struct{}{}
}
}
return result
}
func (set HashSet[E]) Count(predicate func(E) bool) int {
var n int
for item := range set {
if predicate(item) {
n++
}
}
return n
}
func (set HashSet[E]) Reset() {
for item := range set {
delete(set, item)
}
}
type Map[K comparable, V any] map[K]V
func (m Map[K, V]) Len() int { return len(m) }
func (m Map[K, V]) Rename(from, to K) bool {
var v, ok = m[from]
if !ok {
return ok
}
delete(m, from)
m[to] = v
return true
}
func (m Map[K, V]) GetOr(key K, or V) V {
var v, ok = m[key]
if !ok {
return or
}
return v
}
return true
}
func (m Map[K, V]) Pop(key K) (_ V, ok bool) {
var v, exists = m[key]
if !exists {
return v, exists
}
delete(m, key)
return v, true
}
func (m Map[K, V]) GetOr(key K, or V) V {
var v, ok = m[key]
if !ok {
return or
}
return v
}
func (m Map[K, V]) GetOrFn(key K, or func() V) V {
var v, ok = m[key]
if !ok {
return or()
}
return v
}
func (m Map[K, V]) Keys() []K {
var keys = make([]K, 0, len(m))
for k := range m {
keys = append(keys, k)
}
return keys
}
func (m Map[K, V]) Values() []V {
var values = make([]V, 0, len(m))
for _, v := range m {
values = append(values, v)
}
return values
}
type KV[K comparable, V any] struct {
Key K
Value V
}
func (m Map[K, V]) Pairs() []KV[K, V] {
var kvs = make([]KV[K, V], 0, len(m))
for k, v := range m {
kvs = append(kvs, KV[K, V]{
Key: k,
Value: v,
})
}
return kvs
}
func (m Map[K, V]) Select(keys ...K) []V {
var values = make([]V, 0, len(keys))
for _, k := range keys {
var v, ok = m[k]
if ok {
values = append(values, v)
}
}
return values
}
func (m Map[K, V]) Delete(keys ...K) int {
var i int
for _, key := range keys {
delete(m, key)
i++
}
return i
}
func (m Map[K, V]) Contains(key K) bool {
var _, ok = m[key]
return ok
}
func (m Map[K, V]) Reset() {
for key := range m {
delete(m, key)
}
}
func (m Map[K, V]) Clone() Map[K, V] {
var cp = make(Map[K, V], m.Len())
for k, v := range m {
cp[k] = v
}
return cp
}
func (m Map[K, V]) Merge(other map[K]V) {
for k, v := range other {
m[k] = v
}
}
func (m Map[K, V]) MergeWithColl(other map[K]V, collate func(K, V, V) V) {
for k, v := range other {
m[k] = collate(k, m[k], v)
}
}
func (m Map[K, V]) Take(keys ...K) Map[K, V] {
var subset = make(Map[K, V], len(keys))
for _, key := range keys {
var value, ok = m[key]
if ok {
subset[key] = value
}
}
return subset
}
func In[K, V comparable](a, b Map[K, V]) bool {
for k, v := range a {
if v != b[k] {
return false
}
}
return true
}
func InWithEq[K comparable, V any](a, b Map[K, V], eq func(V, V) bool) bool {
for k, v := range a {
if !eq(v, b[k]) {
return false
}
}
return true
}
func IsEqual[K, V comparable](a, b Map[K, V]) bool {
if len(a) != len(b) {
return false
}
return In(a, b)
}
func IsEqualWithEq[K comparable, V any](a, b Map[K, V], eq func(V, V) bool) bool {
if len(a) != len(b) {
return false
}
return InWithEq(a, b, eq)
}
package option
type Opt[E any] struct {
v E
}
func (opt *Opt[E]) Unwrap() E {
if opt.HasValue() {
return opt.v
}
panic("unwrapping Opt: got empty optional value")
}
func (opt *Opt[E]) HasValue() bool {
return opt != nil
}
func (opt *Opt[E]) Unpack() (_ E, ok bool) {
if opt.HasValue() {
return opt.v, true
}
return empty[E](), false
}
func (opt *Opt[E]) Slice() []E {
if opt.HasValue() {
return []E{opt.v}
}
return nil
}
func (opt *Opt[E]) Then(fn func(v E)) {
if opt.HasValue() {
fn(opt.v)
}
}
func (opt *Opt[E]) UnwrapOrEmpty() E {
if opt.HasValue() {
return opt.v
}
return empty[E]()
}
func (opt *Opt[E]) UnwrapOr(or E) E {
if opt.HasValue() {
return opt.v
}
return or
}
func Some[E any](v E) *Opt[E] {
return &Opt[E]{
v: v,
}
}
func SomePtr[E any](ptr *E) *Opt[E] {
if ptr == nil {
return None[E]()
}
return Some[E](*ptr)
}
func None[E any]() *Opt[E] {
return nil
}
func empty[E any]() E {
var v E
return v
}
package result
func Ok[V any](v V) Result[V] {
return Result[V]{Value: v}
}
func Error[V any](err error) Result[V] {
return Result[V]{Error: err}
}
func Wrap[V any](v V, err error) Result[V] {
if err != nil {
return Error[V](err)
}
return Ok[V](v)
}
type Result[V any] struct {
Error error
Value V
}
func (result Result[V]) Unwrap() V {
if result.Error == nil {
return result.Value
}
var v V
var msg = "Result[" + reflect.TypeOf(v).String() + "]: unwrapping empty"
panic(msg)
}
func (result Result[V]) UnwrapOr(or V) V {
if result.Error == nil {
return result.Value
}
return or
}
func (result Result[V]) Ok() bool { return result.Error == nil }
func (result Result[V]) Slice() []V {
if result.Error == nil {
return []V{result.Value}
}
return nil
}
func (result Result[V]) With(f func(V) error) Result[V] {
if result.Error != nil {
return result
}
var err = f(result.Value)
if err != nil {
return Error[V](err)
}
return result
}
func (result Result[V]) WithValue(v V) Result[V] {
if result.Error != nil {
return Ok[V](v)
}
return result
}
func (result Result[V]) WithError(err error) Result[V] {
if result.Error != nil {
return result
}
return Error[V](err)
}
func (result Result[V]) Unpack() (V, error) {
return result.Value, result.Error
}
type Mapper[F, T any] func(F) (T, error)
func Map[F, T any](r Result[F], f Mapper[F, T]) Result[T] {
if !r.Ok() {
return Error[T](r.Error)
}
var v, err = f(r.Value)
if err != nil {
return Error[T](err)
}
return Ok[T](v)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment