Basically self contained statemachines that can be configured for internal or external (complete/partial) state manipulation.
Can be nested inside another cog.
Messages can be passed from layers above (up to the main method) into cogs which are set up for external state change.
The idea is a fractal, hierarchical statemachine whose components are fractal hierarchical statemachines.
Use for whatever. Is probably pretty taxing on memory if your structures get too big.
As with most things in ruby if you are not on top of your variables then things can go badly wrong with your progamme. Take care when writing to states.
my_cog = Cog.new(
read_only: %i[read_only args here],
accessors: %i[things here get writers_and_readers],
args: {
read_only: 'initialize',
args: 'your',
here: 'state.',
things: 'Must include:',
here: 'all accessors and read_onlys'
get: 'and'
writers_and_readers: 'is the argument for the passed block'
}) do
# edit state here, or don't it's up to you what it actually does
end
NB: args
is a terrible name to use for an accessor, don't use args
.
my_cog.turn
return value is last operation of the passed block.
my_cog.turn
# State may have changed
my_cog.turn
# State may have changed again
my_cog.turn
# you get the idea
...
You must have set at least one accessor
my_cog.things = 'new value'
NB: Both accessors and read_onlys get readers.
my_cog.here
=> current value of read only state variable `here`
my_cog.things
=> current value of readable/writable state variable `things`
Have the last evaluated line in the block be :break
Attempts to turn the cog will then result in a CogHasExited
exception.
You don't really have to have to initialize any state variables if you don't want to, you could generate your state in the passed block, but be careful as that could run every turn of the cog.
You don't need to allow access to any state variables if you don't want to.
You can have read_only, read and write (accessors), or neither, there is no write_only.
read_only blacklists anything in accessors and will not generate a writer for that.
The last executed line in the block is yielded by the loop in build_cog
so you can do what you like with your state. eg/ if you only ever want to return state after processing, have the state as the last line, or have nil if you want complete encapsulation.
- use threads Queue object for mailbox in ActorCog
- put a cog in a thread that is listening to a port to gather messages
- talk to another language (probs Go/elixir for pattern matching) via ports using JSON to pass data