decide.rb 0.5.3 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +66 -2
- data/examples/decide.md +2 -2
- data/examples/evolve.md +98 -10
- data/examples/state.md +13 -23
- data/lib/decider/version.rb +1 -1
- data/lib/decider.rb +32 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67225cdb4ecbd0f8577bc2c9744e85958a6fc74252e29014bb957e0c927ee0d9
|
4
|
+
data.tar.gz: 62bf259ddc73c780bc7993e4b597c90e45a047a4981263e81afdc44dcf07399a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7e5a790ab4d45b0d73a189ecdb19907ca139742a61f02dd146c38aa8e61619c55f744095085d89292f3f53976f60ecec17799b3dcc58166a0e5201eb3b8641a
|
7
|
+
data.tar.gz: f27228fda1b9ca07c19cb01d004576ef106de6a2c96c7ce19a4a4b7976b4a5260dca7c91bb59d2404009387152ccd0ce10537e00fe9e76d0e8054992946055d3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,67 @@
|
|
1
|
+
# 0.5.4
|
2
|
+
|
3
|
+
* Add `lmap_on_event` and `rmap_on_event` extensions that takes proc that maps event in or out and returns a new decider
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
decider = Decider.define do
|
7
|
+
initial_state 0
|
8
|
+
|
9
|
+
decide :increase do
|
10
|
+
:increased
|
11
|
+
end
|
12
|
+
|
13
|
+
evolve :increased do
|
14
|
+
state + 1
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
lmap = decider.lmap_on_event(->(event) { event.to_sym })
|
19
|
+
lmap.evolve(0, "increased")
|
20
|
+
# => 1
|
21
|
+
|
22
|
+
rmap = decider.rmap_on_event(->(event) { event.to_s })
|
23
|
+
rmap.decide(:increase, 0)
|
24
|
+
# => "increased"
|
25
|
+
```
|
26
|
+
|
27
|
+
* Add `lmap_on_state` and `rmap_on_state` extensions that takes proc that maps state in or out and returns a new decider
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
decider = Decider.define do
|
31
|
+
initial_state :symbol
|
32
|
+
|
33
|
+
decide :command, :state do
|
34
|
+
emit :called
|
35
|
+
end
|
36
|
+
|
37
|
+
evolve :state, :called do
|
38
|
+
:new_state
|
39
|
+
end
|
40
|
+
end
|
41
|
+
decider.initial_state
|
42
|
+
# => :symbol
|
43
|
+
|
44
|
+
lmap = decider.lmap_on_state(
|
45
|
+
->(state) { state.to_sym }
|
46
|
+
)
|
47
|
+
lmap.initial_state
|
48
|
+
# => :symbol
|
49
|
+
lmap.decide(:command, "symbol")
|
50
|
+
# => [:called]
|
51
|
+
lmap.evolve("symbol", :called)
|
52
|
+
# => :new_state
|
53
|
+
|
54
|
+
rmap = inner.rmap_on_state(
|
55
|
+
->(state) { state.to_s }
|
56
|
+
)
|
57
|
+
rmap.initial_state
|
58
|
+
# => "symbol"
|
59
|
+
rmap.decide(:command, :symbol)
|
60
|
+
# => [:called]
|
61
|
+
rmap.evolve(:symbol, :called)
|
62
|
+
# => "new_state"
|
63
|
+
```
|
64
|
+
|
1
65
|
# 0.5.3
|
2
66
|
|
3
67
|
* Add shortcut for evolving:
|
@@ -28,7 +92,7 @@ inner = Decider.define do
|
|
28
92
|
end
|
29
93
|
end
|
30
94
|
|
31
|
-
outer =
|
95
|
+
outer = inner.dimap_on_event(
|
32
96
|
fl: ->(event) { event.to_sym },
|
33
97
|
fr: ->(event) { event.to_s }
|
34
98
|
)
|
@@ -51,7 +115,7 @@ end
|
|
51
115
|
inner.initial_state
|
52
116
|
# => :symbol
|
53
117
|
|
54
|
-
outer =
|
118
|
+
outer = inner.dimap_on_state(
|
55
119
|
fl: ->(state) { state.to_sym },
|
56
120
|
fr: ->(state) { state.to_s }
|
57
121
|
)
|
data/examples/decide.md
CHANGED
@@ -18,7 +18,7 @@ decider = Decider.define do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
decider.decide Command.new(value: 10), decider.initial_state
|
21
|
-
#> [Event
|
21
|
+
#> [#<data Event value=15>]
|
22
22
|
```
|
23
23
|
|
24
24
|
## Match by command and state
|
@@ -138,7 +138,7 @@ decider = Decider.define do
|
|
138
138
|
emit [:started, command.value]
|
139
139
|
end
|
140
140
|
|
141
|
-
decide proc { [command, state] in [Stop,
|
141
|
+
decide proc { [command, state] in [Stop, :started] } do
|
142
142
|
emit :stopped
|
143
143
|
end
|
144
144
|
end
|
data/examples/evolve.md
CHANGED
@@ -1,25 +1,88 @@
|
|
1
1
|
# Evolve
|
2
2
|
|
3
|
-
##
|
3
|
+
## Match by event
|
4
4
|
|
5
5
|
```ruby
|
6
|
+
Event = Data.define(:value)
|
7
|
+
|
6
8
|
decider = Decider.define do
|
7
9
|
initial_state :initial
|
10
|
+
|
11
|
+
evolve Event do
|
12
|
+
event.value
|
13
|
+
end
|
8
14
|
end
|
15
|
+
|
16
|
+
decider.evolve decider.initial_state, Event.new(value: :changed)
|
17
|
+
#> :changed
|
9
18
|
```
|
10
19
|
|
11
|
-
|
20
|
+
## Match by state and event
|
12
21
|
|
13
22
|
```ruby
|
23
|
+
decider = Decider.define do
|
24
|
+
initial_state :turned_off
|
25
|
+
|
26
|
+
evolve :turned_on, :turned_off do
|
27
|
+
event
|
28
|
+
end
|
29
|
+
|
30
|
+
evolve :turned_off, :turned_on do
|
31
|
+
event
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
decider.evolve decider.initial_state, :turned_on
|
36
|
+
#> :turned_on
|
37
|
+
decider.evolve :turned_on, :turned_off
|
38
|
+
#> :turned_off
|
39
|
+
decider.evolve :turned_on, :unknown
|
40
|
+
#> :turned_on
|
41
|
+
```
|
42
|
+
|
43
|
+
## Match by pattern matching
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
State = Data.define(:value)
|
47
|
+
Event = Data.define(:value)
|
48
|
+
|
49
|
+
decider = Decider.define do
|
50
|
+
initial_state State.new(value: :turned_off)
|
51
|
+
|
52
|
+
evolve proc { [state, event] in [State(value: :turned_off), Event(value: :turned_on)] } do
|
53
|
+
state.with(value: event.value)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
decider.evolve decider.initial_state, Event.new(value: :turned_on)
|
58
|
+
#> #<data State value=:turned_on>
|
14
59
|
decider.evolve decider.initial_state, :unknown
|
60
|
+
#> #<data State value=:turned_off>
|
61
|
+
```
|
62
|
+
|
63
|
+
## Handling unknown events
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
decider = Decider.define do
|
67
|
+
initial_state :initial
|
68
|
+
end
|
69
|
+
|
70
|
+
decider.decide decider.initial_state, :initial
|
15
71
|
#> :initial
|
16
72
|
```
|
17
73
|
|
18
|
-
|
74
|
+
If you want to raise error, define a catch-all as last one:
|
19
75
|
|
20
76
|
```ruby
|
21
|
-
decider
|
22
|
-
|
77
|
+
decider = Decider.define do
|
78
|
+
initial_state :initial
|
79
|
+
|
80
|
+
evolve proc { true } do
|
81
|
+
raise ArgumentError, "Unknown event #{event}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
decider.evolve decider.initial_state, :unknown
|
85
|
+
#> Unknown event unknown (ArgumentError)
|
23
86
|
```
|
24
87
|
|
25
88
|
## Events
|
@@ -30,11 +93,11 @@ Events can be primitives like symbols:
|
|
30
93
|
decider = Decider.define do
|
31
94
|
initial_state :initial
|
32
95
|
|
33
|
-
evolve :started do
|
96
|
+
evolve :started do
|
34
97
|
:started
|
35
98
|
end
|
36
99
|
|
37
|
-
evolve :stopped do
|
100
|
+
evolve :stopped do
|
38
101
|
:stopped
|
39
102
|
end
|
40
103
|
end
|
@@ -50,13 +113,38 @@ Stopped = Data.define
|
|
50
113
|
decider = Decider.define do
|
51
114
|
initial_state State.new(speed: 0)
|
52
115
|
|
53
|
-
evolve Started do
|
54
|
-
|
116
|
+
evolve State, Started do
|
117
|
+
state.with(speed: event.speed)
|
55
118
|
end
|
56
119
|
|
57
|
-
evolve Stopped do
|
120
|
+
evolve State, Stopped do
|
58
121
|
State.new(speed: 0)
|
59
122
|
end
|
60
123
|
end
|
61
124
|
```
|
62
125
|
|
126
|
+
## Calculate state
|
127
|
+
|
128
|
+
In most cases you want to take a collection of events and reduce them with `evolve` to calculate the state, like:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
decider = Decider.define do
|
132
|
+
initial_state 0
|
133
|
+
|
134
|
+
evolve :increased do
|
135
|
+
state + 1
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
[:increased, :increased].reduce(decider.initial_state) { |state, event| decider.evolve(state, event) }
|
140
|
+
#> 2
|
141
|
+
```
|
142
|
+
|
143
|
+
You can shortcut that with `&`:
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
[:increased, :increased].reduce(decider.initial_state, &decider.method(:evolve))
|
147
|
+
#> 2
|
148
|
+
[:increased, :increased].reduce(decider.initial_state, &decider.evolve)
|
149
|
+
#> 2
|
150
|
+
```
|
data/examples/state.md
CHANGED
@@ -8,11 +8,11 @@ State = Data.define(:value)
|
|
8
8
|
decider = Decider.define do
|
9
9
|
initial_state State.new(value: 0)
|
10
10
|
|
11
|
-
decide Commands::Command do
|
12
|
-
|
11
|
+
decide Commands::Command do
|
12
|
+
emit Events::Event.new(value: command.value)
|
13
13
|
end
|
14
14
|
|
15
|
-
evolve Events::Event do
|
15
|
+
evolve Events::Event do
|
16
16
|
state.with(value: state.value + 1)
|
17
17
|
end
|
18
18
|
end
|
@@ -24,26 +24,16 @@ end
|
|
24
24
|
decider = Decider.define do
|
25
25
|
initial_state :turned_off
|
26
26
|
|
27
|
-
decide Commands::TurnOn do
|
28
|
-
|
29
|
-
in :turned_off
|
30
|
-
[Events::TurnedOn.new]
|
31
|
-
else
|
32
|
-
[]
|
33
|
-
end
|
27
|
+
decide Commands::TurnOn, :turned_off do
|
28
|
+
emit Events::TurnedOn.new
|
34
29
|
end
|
35
30
|
|
36
|
-
decide Commands::TurnOff do
|
37
|
-
|
38
|
-
in :turned_on
|
39
|
-
[Events::TurnedOn.new]
|
40
|
-
else
|
41
|
-
[]
|
42
|
-
end
|
31
|
+
decide Commands::TurnOff, :turned_on do
|
32
|
+
emit Events::TurnedOff.new
|
43
33
|
end
|
44
34
|
|
45
|
-
evolve Events::TurnedOn do
|
46
|
-
:
|
35
|
+
evolve Events::TurnedOn do
|
36
|
+
:turned_on
|
47
37
|
end
|
48
38
|
end
|
49
39
|
```
|
@@ -54,12 +44,12 @@ end
|
|
54
44
|
decider = Decider.define do
|
55
45
|
initial_state []
|
56
46
|
|
57
|
-
decide Commands::Command do
|
58
|
-
|
47
|
+
decide Commands::Command, [] do
|
48
|
+
emit Events::Event.new(value: command.value)
|
59
49
|
end
|
60
50
|
|
61
|
-
evolve Events::Event do
|
62
|
-
state
|
51
|
+
evolve Events::Event do
|
52
|
+
state + [event]
|
63
53
|
end
|
64
54
|
end
|
65
55
|
```
|
data/lib/decider/version.rb
CHANGED
data/lib/decider.rb
CHANGED
@@ -108,10 +108,26 @@ module Decider
|
|
108
108
|
context.instance_exec(&terminal)
|
109
109
|
end
|
110
110
|
|
111
|
+
define_method(:lmap_on_state) do |fn|
|
112
|
+
Decider.lmap_on_state(self, fn)
|
113
|
+
end
|
114
|
+
|
115
|
+
define_method(:rmap_on_state) do |fn|
|
116
|
+
Decider.rmap_on_state(self, fn)
|
117
|
+
end
|
118
|
+
|
111
119
|
define_method(:dimap_on_state) do |fl:, fr:|
|
112
120
|
Decider.dimap_on_state(self, fl: fl, fr: fr)
|
113
121
|
end
|
114
122
|
|
123
|
+
define_method(:lmap_on_event) do |fn|
|
124
|
+
Decider.lmap_on_event(self, fn)
|
125
|
+
end
|
126
|
+
|
127
|
+
define_method(:rmap_on_event) do |fn|
|
128
|
+
Decider.rmap_on_event(self, fn)
|
129
|
+
end
|
130
|
+
|
115
131
|
define_method(:dimap_on_event) do |fl:, fr:|
|
116
132
|
Decider.dimap_on_event(self, fl: fl, fr: fr)
|
117
133
|
end
|
@@ -211,6 +227,14 @@ module Decider
|
|
211
227
|
end
|
212
228
|
end
|
213
229
|
|
230
|
+
def self.lmap_on_state(decider, fn)
|
231
|
+
dimap_on_state(decider, fl: fn, fr: ->(state) { state })
|
232
|
+
end
|
233
|
+
|
234
|
+
def self.rmap_on_state(decider, fn)
|
235
|
+
dimap_on_state(decider, fl: ->(state) { state }, fr: fn)
|
236
|
+
end
|
237
|
+
|
214
238
|
def self.dimap_on_state(decider, fl:, fr:)
|
215
239
|
define do
|
216
240
|
initial_state fr.call(decider.initial_state)
|
@@ -229,6 +253,14 @@ module Decider
|
|
229
253
|
end
|
230
254
|
end
|
231
255
|
|
256
|
+
def self.lmap_on_event(decider, fn)
|
257
|
+
dimap_on_event(decider, fl: fn, fr: ->(event) { event })
|
258
|
+
end
|
259
|
+
|
260
|
+
def self.rmap_on_event(decider, fn)
|
261
|
+
dimap_on_event(decider, fl: ->(event) { event }, fr: fn)
|
262
|
+
end
|
263
|
+
|
232
264
|
def self.dimap_on_event(decider, fl:, fr:)
|
233
265
|
define do
|
234
266
|
initial_state decider.initial_state
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: decide.rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Dudulski
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-06-21 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: concurrent-ruby
|