diff --git a/Var.go b/Var.go new file mode 100644 index 0000000..e7d6d97 --- /dev/null +++ b/Var.go @@ -0,0 +1,101 @@ +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 +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..03ff6c8 --- /dev/null +++ b/go.mod @@ -0,0 +1,7 @@ +module gitlab.com/Pixdigit/lazy + +require ( + github.com/pkg/errors v0.8.1 + gitlab.com/Pixdigit/goTestTools v0.0.0-20180720152516-ad30e7e0c720 + gitlab.com/Pixdigit/uniqueID v1.0.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b7824bc --- /dev/null +++ b/go.sum @@ -0,0 +1,6 @@ +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +gitlab.com/Pixdigit/goTestTools v0.0.0-20180720152516-ad30e7e0c720 h1:kQXIufpMQqyxsg9Uq0Hu2HxBS1fROHG3mNcKqlSIRqY= +gitlab.com/Pixdigit/goTestTools v0.0.0-20180720152516-ad30e7e0c720/go.mod h1:jvhQAivWS1NiM0wS+fhnlZOBytsMHv69a8BbpghrHYU= +gitlab.com/Pixdigit/uniqueID v1.0.0 h1:I7Q49mOG6cAbgwtviFUvDwDr01JMm5h/vaatqafLWeQ= +gitlab.com/Pixdigit/uniqueID v1.0.0/go.mod h1:tcfI4jl0vg20J/auXSuCOhCPR9b4gnHJgwxeyHKroTg= diff --git a/var_test.go b/var_test.go new file mode 100644 index 0000000..05627b9 --- /dev/null +++ b/var_test.go @@ -0,0 +1,22 @@ +package pixelMenu + +import ( + "testing" + + tools "gitlab.com/Pixdigit/goTestTools" +) + +func TestResolverExample(t *testing.T) { + p1 := Invariant(1) + p2 := Invariant(2) + p3 := Invariant(3) + p4 := Invariant(4) + + result := Div(Sub(Mul(Add(p1, p2), p3), p4), Invariant(1)) + result.Resolve() + tools.Test(result.Value == 5, "invalid result", t) + tools.Test(result.HasDependency(p1), "No dependency detected", t) + tools.Test(result.HasDependency(p2), "No dependency detected", t) + tools.Test(result.HasDependency(p3), "No dependency detected", t) + tools.Test(result.HasDependency(p4), "No dependency detected", t) +}