On Wed, 23 Aug 2017 09:48:14 BST roger peppe <[email protected]> wrote:
> On 23 August 2017 at 09:40, roger peppe <[email protected]> wrote:
> > On 23 August 2017 at 09:23, MartinG <[email protected]> wrote:
> >> Thanks for the fantastic explanation folks.
> >>
> >> I wonder if I can ask advice on how to improve my use case. I have a stru
> ct
> >> type that represents a state machine and each state is handled by a
> >> different method on that type, each with the same signature I use a
> >> function variable to represent the current state and it is simply set to
> >> point at one of the methods. The state is modified frequently, hence my
> >> problem.
> >>
> >> The options I can think of are:
> >>
> >> 1) Define another type (probably based on int or similar) representing the
> >> current state and switch on that instead of using a function type. This
> >> feels inelegant and avoids using function types on one of the scenarios th
> ey
> >> seem to be designed for.
> >> 2) Define non-method related functions with a similar signature, but that
> >> also take my base type as an additional parameter. I believe this will
> >> avoid the allocation, but also feels wrong because these functions really
> >> "belong" to my base type so should be methods.
> >>
> >> Any other possibilities?
> >
> > You could use method expressions.
> >
> > For example:
> >
> > https://play.golang.org/p/9H1n-CevNJ
>
> Actually, it occurs to me that using method expressions in this way is
> actually more powerful, because the state can be manipulated independently
> of the state transitions. You could use this, for example, to fork the
> state machine and run it concurrently from an arbitrary state.
I find regular functions much cleaner (and a closer analog of
a digital FSM). See for example:
https://play.golang.org/p/MpX_lNT4rS
Basically
type state func(inputType) state
func reset() { return initial }
func initial(i inputType) state {
if needChange(i) { return stateOne }
return initial
}
func stateOne(i inputType) state {
// etc. etc.
}
func main() {
s := reset()
for s != nil {
s := s(readInput())
}
}
and so on. This is a Mealy machine, where the next state
depends on the current state and current input (in s/w not
much use for a Moore machine unless you are driving/simulating
some regular physical process, in which case you don't need
any input parameter). If you want a side effecting FSM, pass
in a ptr to some mutable state.
Since these are essentially pure functions you can run them in
parallel. I tend to think use of methods requires more
boilerplate and is more obfuscating.
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.