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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d34cbcdaf2713fe8bd44d975d9d9bd40801af014cc84e3e37c69bee8ef14b1b2
4
- data.tar.gz: 8f82294e16473b2ae75040cd5b1da79c3ddca4d77f103ea86c57a498f004b1d4
3
+ metadata.gz: 67225cdb4ecbd0f8577bc2c9744e85958a6fc74252e29014bb957e0c927ee0d9
4
+ data.tar.gz: 62bf259ddc73c780bc7993e4b597c90e45a047a4981263e81afdc44dcf07399a
5
5
  SHA512:
6
- metadata.gz: 400fb7bb3bb77f17578bf15b36f4d88213694562c1626736c0433ddce2b1fa43ad84dd3a87b6b8eb641f862838aff0848210fe40caeffb20234779aa6db0b8be
7
- data.tar.gz: 7b8ecedf12b070c414aa7a41d30675d0038f439f6d892990ad74a9289ad3d2df006c78ea402557b3f80c2ec36343d434563b44d58f267b30af919d848ded3469
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 = decider.dimap_on_event(
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 = decider.dimap_on_state(
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.new(value: 15)]
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, [:started, _]] } do
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
- ## Handling unknown events
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
- Return state (nothing changed) by default:
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
- Raise error when using `evolve!`:
74
+ If you want to raise error, define a catch-all as last one:
19
75
 
20
76
  ```ruby
21
- decider.evolve! decider.initial_state, :unknown
22
- #> raise ArgumentError, Unknown event
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 |state, event|
96
+ evolve :started do
34
97
  :started
35
98
  end
36
99
 
37
- evolve :stopped do |state, event|
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 |state, event|
54
- State.new(speed: event.speed)
116
+ evolve State, Started do
117
+ state.with(speed: event.speed)
55
118
  end
56
119
 
57
- evolve Stopped do |state, event|
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 |command, state|
12
- [Events::Event.new(value: command.value)]
11
+ decide Commands::Command do
12
+ emit Events::Event.new(value: command.value)
13
13
  end
14
14
 
15
- evolve Events::Event do |state, event|
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 |_command, state|
28
- case state
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 |_command, state|
37
- case state
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 |_state, _event|
46
- :turned_off
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 |command, _state|
58
- [Events::Event.new(value: command.value)]
47
+ decide Commands::Command, [] do
48
+ emit Events::Event.new(value: command.value)
59
49
  end
60
50
 
61
- evolve Events::Event do |state, event|
62
- state = state + [event]
51
+ evolve Events::Event do
52
+ state + [event]
63
53
  end
64
54
  end
65
55
  ```
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Decider
4
- VERSION = "0.5.3"
4
+ VERSION = "0.5.4"
5
5
  end
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.3
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-04-15 00:00:00.000000000 Z
10
+ date: 2025-06-21 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: concurrent-ruby