qmuntal / stateless

Go library for creating finite state machines
BSD 2-Clause "Simplified" License
942 stars 49 forks source link

[Feature request] Ability to configure name of ActionFunc and GuardFunc #83

Open cloverrose opened 1 month ago

cloverrose commented 1 month ago

Hello, I started using this cool package. I really like ToGraph feature. I can check state machine visually. Especially, Drawing ActionFunc name and GuardFunc name automatically by using reflection is really nice feature.

To make code more controllable, I was thinking to wrap stateless.StatemMachine to always receive defined type (MyType) as 1st argument.

type MyType struct {
    Ready bool
}

This is thin wrapper

type StateMachine struct {
    sm *stateless.StateMachine
}

type GuardFunc func(ctx context.Context, myType MyType, args ...any) bool

func (f GuardFunc) Convert() stateless.GuardFunc {
    return func(ctx context.Context, args ...any) bool {
        myType := args[0].(MyType)
        return f(ctx, myType, args[1:]...)
    }
}

func (sm *StateMachine) Permit(src State, trig Trigger, dest State, guards ...GuardFunc) {
    conv := make([]stateless.GuardFunc, len(guards))
    for i, g := range guards {
        conv[i] = g.Convert()
    }
    sm.sm.Configure(src).Permit(trig, dest, conv...)
}

Example guard Func is like this

func isReady(ctx context.Context, myType MyType, args ...any) bool {
    return myType.Ready
}

It works except for ToGraph and error message. Since actual guard Func is anonymous function, which created in Convert(), the guard func is named like func1.

I wonder if this library support name of func as optional parameter or allow user to use guardCondition directly.