A small go library to lazily calculate dependent variables.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
1.8 KiB

package pixelMenu
import (
"github.com/pkg/errors"
"gitlab.com/Pixdigit/uniqueID"
)
var ErrCircularDependency = errors.New("circular dependency while resolving")
var VarIDSpace = uniqueID.IDSpace{}
type Var struct {
id uniqueID.ID
isResolving bool
IsResolved bool
Value float64
evaluator func() float64
dependencies []Var
}
func Invariant(value float64) Var {
return Var{
VarIDSpace.NewID(),
false,
true,
value,
func() float64 { return value },
make([]Var, 0),
}
}
func NewVar() Var {
return Var{
VarIDSpace.NewID(),
false,
false,
0,
func() float64 { return 0 },
make([]Var, 0),
}
}
func Combine(p1, p2 Var, combinator func(float64, float64) float64) Var {
return Var{
VarIDSpace.NewID(),
false,
false,
0,
func() float64 { return combinator(p1.evaluator(), p2.evaluator()) },
[]Var{p1, p2},
}
}
func Add(p1, p2 Var) Var {
return Combine(p1, p2, func(arg1 float64, arg2 float64) float64 {
return arg1 + arg2
})
}
func Sub(p1, p2 Var) Var {
return Combine(p1, p2, func(arg1 float64, arg2 float64) float64 {
return arg1 - arg2
})
}
func Mul(p1, p2 Var) Var {
return Combine(p1, p2, func(arg1 float64, arg2 float64) float64 {
return arg1 * arg2
})
}
func Div(p1, p2 Var) Var {
return Combine(p1, p2, func(arg1 float64, arg2 float64) float64 {
return arg1 / arg2
})
}
func (p *Var) HasDependency(p2 Var) bool {
for _, dep := range p.dependencies {
if dep.id == p2.id {
return true
}
if dep.HasDependency(p2) {
return true
}
}
return false
}
func (p *Var) Resolve() error {
p.isResolving = true
defer func() { p.isResolving = false }()
//Assume user has done dependency check
for _, dep := range p.dependencies {
if !dep.IsResolved {
dep.Resolve()
}
}
p.Value = p.evaluator()
p.IsResolved = true
return nil
}