pirog

package module
v1.1.8 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2024 License: BSD-3-Clause Imports: 13 Imported by: 4

README

License tag Test goreport

pirog

Golang mapreduce primitives and other cool stuff from perl and javascript.

Main idea is to use commonly known and well proven constructions introduced in other languages. Constructions have distinguishable appearance and pretend to be a part of the language rather than just functions.

Useage

Just import it as is, but if you want and have enough dare, use special symbol to package reference like

import . "github.com/vany/pirog"

Then just use it.

MAP(array, callback) array // the cause of this lib

This is part of mapreduce and almost full copy of perl's map. It transforms input array to output array with callback function.

type Person struct {
    FirstName  string
    SecondName string
}

people := []Person{{"Vasya", "Pupkin"}, {"Vasya", "Lozhkin"}, {"Salvador", "Dalí"}}
out := MAP(people, func(p Person) string{
	return fmt.Sprintf("%s %s", p.FirstName, p.SecondName)
})

out now is []string containing concatenated names.

GREP(array, callback) array // from perl

This is filter, that leaves only that elements that trigerrs callback function to return true

fakePeople := GREP(out, func(s string) bool {
    return strings.HasSuffix(s, "Pupkin")
})

fakePeople now is []string and contains just "Vasya Pupkin"

REDUCE(init, array, callback) aggregate // should be in perl

Takes array and applies callback function to aggregate object and each element of array. Starts from init.

x := REDUCE(1+0i, EXPLODE(6, func(i int) complex128 {
    return 0 + 1i
}), func(i int, in complex128, acc *complex128) {
    *acc *= in
})
// rounds dot for 3π so result will be -1
EXPLODE(number, callback) array // syntax sugar

Explodes number to range of values

smallEnglishLetters := EXPLODE(26, func(in int) string { return string([]byte{byte('a' + in)}) }) {
KEYS(map) array // from perl

Returns just full set of keys from map to use it further

artistsMap := map[string]string{
	"Vasya":"Lozhkin",
	"Salvador":"Dalí",
}
AllLozhkins := GREP(KEYS(artistsMap), func(in string) string }{
	return artistsMap[in] == "Lozhkin" 
})

AllLozhkins will be []string{"Vasya"}

VALUES(map) array // from perl

Returns full set of values from map to use it further

HAVEKEY(map, key) bool // syntax sugar

Just indicates do we have key in map, or no.

ANYKEY(map) key // syntax sugar

Returns any arbitrary key from map.

ANYWITHDRAW(map) key, value // common operation with mapped job queue

Chooses arbitrary key from map, delete it and return.

FLATLIST(list of lists) list // helper for map

Flaterns list of lists, used when you have MAP in MAP, but need flat list outside.

COALESCE(args...) value // syntax sugar

Return first not empty value from args. Caution, all arguments will be evaluated.

COALESCE("", "", "10", "", "213231243") == "10"
MUST(err)

Validates err for nil and panics other way. When you in CLI or sure that here can not be an error.

MUST(json.NewEncoder(buff).Encode(object))

MUST2 - MUST5

Same as must, but returns values number at the end of name is number of the arguments.

files := GREP(MUST2(os.ReadDir(".")), func (in os.DirEntry) bool {
	return !in.IsDir()
})
REF(value) reference

Sometime functions return struct, and this struct is located on stack, this function moves this struct into heap;

logger := REF(zerolog.New)
SWAPPER(array) func

Same as reflect.Swapper(), generates function of two int params to swap values in specified array

arr := []os.File{f1,f2,f3}
swapFiles := SWAPPER(arr)
swapFiles(1,2)
TYPEOK(interface type conversion) bool // syntax sugar

Returns just ok part from conversion, used for checking interface type

v := any(os.File{})
if TYPEOK(v.(os.File)) { ... }
SEND(ctx, chan, val) // hidden select

Send to unbuffered chan, exit if context canceled

go func() {SEND(ctx, chan, "value"); print("continue execution")}()
cancel()
NBSEND(chan, val) bool // hidden select

Send to unbuffered chan, nonblocking

if NBSEND(chan, "value") { ... }
RECV(ctx, chan) val, bool // hidden select

Receive blockingly from channel, exit if context cancelled

if val, ok := RECV(ctx, ch); ok {
	...
}
NBRECV(chan) val, bool // hidden select

Receive non blockingly from channel

if val, ok := NBRECV(ch); ok {
	...
}
WAIT(ctx, chan, cb()) // hidden select

Nonparallel promise on channel.

go WAIT(ctx, ch, func(T) {
    ...	
})
FANOUT(chan) copyer() // closure with channels

Creates copyer of chan, all events put in base chan will be copied to a copies. All chan events will be handled properly. If original chan closing all copies will be closed.

func serveClient(original chan T) {
	generator := FANOUT(original)
    for ... {
        c, d := generator()
        defer d()
        go finc(){ for msg := range c { ... ; ... ; d() }  }()
        ...
    }
}
FANIN(chan) generator(), destructor() // closure with channels

Creates attacher to sink chan. All messages from attached chans will be copied to main chan.

    generator, destructor  := FANIN(ch)
    go func(){ for range ch {  ...  } }()
    c1, c2 ,c3 := generator(), generator(), generator() 
	c1 <- msg1
	c2 <- msg2
	...
	destructor()
	

General purpose functions

Set of functions, you always want to have.

ToJson(any)string // syntax sugar

Returns json representation of argument or dies.

jsonPeople := MAP(people, func(p Person) string{ return ToJson(p) })

jsonPeople becomes slice of strings contained json representation of people array elements.

EXEC(ctx, command, stdin) code, stdout, stderr, err

Same as perl backticks, run external command.

/// look at tests ///
ExecuteOnAllFields(ctx, storage, "method_name") error // reflect cycle for fields

Executes method_name(ctx) on all non nil interface fields in storage, used to initialize application.

app := App{
	Connection: fancy.NewConnection(cfg),
}
ExecuteOnAllFields(ctx, &app, "InitStage1")
InjectComponents(storage) // reflect cycle for tagged fields

Takes all *struct and interface fields and puts it in its fields found fields by type.

type Component struct { L *Logger `inject:"logger"`}
app := App{
    Logger:    new(Logger), `injectable:"logger"`
	Component: new(Component),	
}
InjectComponents(&app)
app.Component.L.Info("Component now have logger injected")
CleanComponents(storage) // reflect cycle

Uninject (set nil) all components (tagged by inject or injectable)

func (c *Component)Stop(ctx context.Context) error
    CleanComponents(&c)
    return nil
}
DEBUG // build dependent constant

Constant based on debug build tag. Code in if statement will not be compiled if DEBUG is false (debug tag not set)

if pirog.DEBUG { logger.Debug(<some toughly evaluted info you want not to evauate >) }
go run -tags debug programm.go
CHANGEWATCHER(name,var) func(var)

Returns if variable was changed from previous call. If DEBUG is set, prints point in code to stdout.

cw := CHANGEWATCHER("mainchangewatcher", "")
for {
	// some code that can change variable
	_ = DEBUG && cw(variable)
}
Subscription SubscriptionObject := NewSubscription() // map of arrays of channels with mutex

Subscribe to some type of event or object ids.

s := NewSubscription[string, any]()
achan, bchan :=  s.Subscribe("now"), s.Subscribe("now") 
s.Notify("now", time.Now())
... <- achan ...
s.Close("Now")
... _, closed := <- bchan
REQUEST(req) // struct of request with response channel

Create answerable request to send it over channel

c <- REQUEST[ReqType, RespType](req).THEN(ctx, func(ctx context.Context, resp RespType) {
	// Do something with resp
})

go func() {
	r := <- c
	// calc resp
	r.RESPOND(ctx, resp)
} ()

Requests and pull requests are welcome.

Documentation

Index

Constants

View Source
const DEBUG = false

Variables

This section is empty.

Functions

func ANYKEY

func ANYKEY[K comparable, V any](in map[K]V) K

ANYKEY - Returns any arbitrary key from map.

func ANYWITHDRAW added in v1.0.4

func ANYWITHDRAW[K comparable, V any](in map[K]V) (K, V)

ANYWITHDRAW - Chooses arbitrary key from map, delete it and return.

func COALESCE added in v1.1.2

func COALESCE[T comparable](in ...T) T

COALESCE - return first non zero(false) value

func CleanComponents added in v1.1.6

func CleanComponents(a any)

func EXEC added in v1.1.7

func EXEC(ctx context.Context, path string, stdin io.Reader) (code int, stdout, stderr *bytes.Buffer, err error)

func EXPLODE added in v1.0.1

func EXPLODE[T any](num int, f func(int) T) []T

EXPLODE - Explodes number to range of values.

func ExecuteOnAllFields added in v1.0.6

func ExecuteOnAllFields(ctx context.Context, a any, mname string) error

ExecuteOnAllFields - On all interface fields run method by name

func FANIN added in v1.1.0

func FANIN[T any](src chan T) (generator func() chan T, destructor func())

FANIN - returns channel generator that push all incoming into one channel

func FANOUT added in v1.1.0

func FANOUT[T any](src <-chan T) (
	generator func() (tap <-chan T, destructor func()),
)

FANOUT - returns function that returns channels attached to source chan

func FLATLIST added in v1.0.2

func FLATLIST[T any](arrs [][]T) []T

FLATLIST - flaterns list of lists to just list

func GREP

func GREP[T any](arr []T, f func(T) bool) []T

GREP - This is filter, that leaves only that elements that trigerrs callback function to return true

func HAVEKEY

func HAVEKEY[K comparable, V any](in map[K]V, key K) bool

HAVEKEY - Just indicates do we have key in map, or no.

func InjectComponents added in v1.1.1

func InjectComponents(a any)

InjectComponents - search for corresponding fields in fields and put references there

func KEYS

func KEYS[K comparable, V any](in map[K]V) []K

KEYS - Returns full set of keys from map to use it further

func MAP

func MAP[IN any, OUT any](arr []IN, f func(IN) OUT) []OUT

MAP - This is part of mapreduce and almost full copy of perl's map. It transforms input array to output array with callback function.

func MAPCONCAT added in v1.1.8

func MAPCONCAT[T any](a, b map[string]T) (ret map[string]T)

MAPCONCAT - returns two maps concatenated

func MUST

func MUST(err error)

func MUST2 added in v1.0.1

func MUST2[T1 any](a1 T1, err error) T1

func MUST3 added in v1.0.1

func MUST3[T1 any, T2 any](a1 T1, a2 T2, err error) (T1, T2)

func MUST4 added in v1.0.1

func MUST4[T1 any, T2 any, T3 any](a1 T1, a2 T2, a3 T3, err error) (T1, T2, T3)

func MUST5 added in v1.0.1

func MUST5[T1 any, T2 any, T3 any, T4 any](a1 T1, a2 T2, a3 T3, a4 T4, err error) (T1, T2, T3, T4)

func NBRECV added in v1.1.3

func NBRECV[T any](ch <-chan T) (T, bool)

NBRECV - receive from chan obeying context

func NBSEND added in v1.0.9

func NBSEND[T any](ch chan<- T, val T) bool

NBSEND - Sends to channel nonblockingly

func RECV added in v1.1.0

func RECV[T any](ctx context.Context, ch <-chan T) (T, bool)

RECV - receive from chan obeying context

func REDUCE added in v1.0.1

func REDUCE[IN any, ACC any](init ACC, in []IN, f func(int, IN, *ACC)) *ACC

REDUCE - Takes array and applies callback function to aggregate object and each element of array. Starts from init.

func REF added in v1.1.8

func REF[T any](in T) *T

REF - used when constructor is crazy by design

func SEND added in v1.0.7

func SEND[T any](ctx context.Context, ch chan<- T, val T)

SEND - Sends to channel obeying cancel of context

func SWAPPER added in v1.0.1

func SWAPPER[T any](slice []T) func(i, j int)

SWAPPER - same as reflect.Swapper, but template

func TERNARY

func TERNARY[T any](e bool, a, b T) T

TERNARY - ternary operator

func TYPEOK added in v1.0.1

func TYPEOK[T any](_ T, ok bool) bool

TYPEOK - strip value from explicit interface type conversion

func ToJson

func ToJson(in any) string

func VALUES added in v1.0.4

func VALUES[K comparable, V any](in map[K]V) []V

VALUES - Returns full set of values from map to use it further

func WAIT added in v1.1.0

func WAIT[T any](ctx context.Context, ch <-chan T, cb func(T))

WAIT - for message on chan and do action once, obeying context

Types

type CHANGEWATCHERFUNC added in v1.1.1

type CHANGEWATCHERFUNC[T comparable] func(n T) bool

func CHANGEWATCHER added in v1.1.1

func CHANGEWATCHER[T comparable](name string, o T) CHANGEWATCHERFUNC[T]

CHANGEWATCHER - was variabe changed from previous call

type COMMENTABLETYPE added in v1.1.3

type COMMENTABLETYPE[T any] struct{ T T }

func COMMENTABLE added in v1.1.3

func COMMENTABLE[T any](in T) COMMENTABLETYPE[T]

func (*COMMENTABLETYPE[T]) MarshalYAML added in v1.1.3

func (C *COMMENTABLETYPE[T]) MarshalYAML() (interface{}, error)

type REQUESTTYPE added in v1.1.6

type REQUESTTYPE[REQ any, RES any] struct {
	REQ REQ
	RES chan RES
}

func REQUEST added in v1.1.6

func REQUEST[REQ any, RES any](req REQ) REQUESTTYPE[REQ, RES]

func (REQUESTTYPE[REQ, RES]) RESPOND added in v1.1.6

func (r REQUESTTYPE[REQ, RES]) RESPOND(ctx context.Context, res RES) REQUESTTYPE[REQ, RES]

func (REQUESTTYPE[REQ, RES]) SEND added in v1.1.6

func (r REQUESTTYPE[REQ, RES]) SEND(ctx context.Context, c chan REQUESTTYPE[REQ, RES]) REQUESTTYPE[REQ, RES]

func (REQUESTTYPE[REQ, RES]) THEN added in v1.1.6

func (r REQUESTTYPE[REQ, RES]) THEN(ctx context.Context, f func(context.Context, RES)) REQUESTTYPE[REQ, RES]

type SUBSCRIPTION added in v1.1.4

type SUBSCRIPTION[A comparable, T any] struct {
	sync.Mutex
	M map[A][]chan T
}

func NewSUBSCRIPTION added in v1.1.4

func NewSUBSCRIPTION[A comparable, T any]() *SUBSCRIPTION[A, T]

func (*SUBSCRIPTION[A, T]) Close added in v1.1.4

func (s *SUBSCRIPTION[A, T]) Close(id A)

func (*SUBSCRIPTION[A, T]) Has added in v1.1.7

func (s *SUBSCRIPTION[A, T]) Has(id A) bool

func (*SUBSCRIPTION[A, T]) Notify added in v1.1.4

func (s *SUBSCRIPTION[A, T]) Notify(id A, data T)

func (*SUBSCRIPTION[A, T]) Subscribe added in v1.1.4

func (s *SUBSCRIPTION[A, T]) Subscribe(id A) chan T

func (*SUBSCRIPTION[A, T]) UnSubscribe added in v1.1.6

func (s *SUBSCRIPTION[A, T]) UnSubscribe(id A, c chan T)

Jump to

Keyboard shortcuts

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