accessory 0.1.4 → 0.1.9
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/lib/accessory.rb +3 -3
- data/lib/accessory/access.rb +55 -40
- data/lib/accessory/accessor.rb +168 -19
- data/lib/accessory/accessors/all_accessor.rb +21 -6
- data/lib/accessory/accessors/attribute_accessor.rb +16 -12
- data/lib/accessory/accessors/between_each_accessor.rb +34 -18
- data/lib/accessory/accessors/betwixt_accessor.rb +43 -28
- data/lib/accessory/accessors/filter_accessor.rb +20 -6
- data/lib/accessory/accessors/first_accessor.rb +18 -12
- data/lib/accessory/accessors/instance_variable_accessor.rb +13 -11
- data/lib/accessory/accessors/last_accessor.rb +18 -12
- data/lib/accessory/accessors/subscript_accessor.rb +20 -13
- data/lib/accessory/bound_lens.rb +139 -0
- data/lib/accessory/lens.rb +202 -56
- data/lib/accessory/traversal_position/enumerable_at_offset.rb +28 -0
- data/lib/accessory/traversal_position/enumerable_before_offset.rb +55 -0
- data/lib/accessory/version.rb +1 -1
- metadata +5 -4
- data/lib/accessory/array_cursor_position.rb +0 -32
- data/lib/accessory/lens_path.rb +0 -219
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c03753edaa94362541af5695a93547b6e1f3565f37aa82e7536b3e81d212eb7c
|
4
|
+
data.tar.gz: a3584fbf0b4ee32555feccd642c7225fd6c6f8f85563fcb03b542624f36f7660
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61015ff40a150d474e43ec454a4c50cb0fd4021660a10cf65d61cd69ec4abe3293523fa53cceda199da7996ed5bea160efc45bf826724647fbc7020f0c666b57
|
7
|
+
data.tar.gz: 3ec8ca3a2f53df27e958621997102d6d10220a15f26c48dc6cdb3f56403f387d629d531433d93f05e6ced2f30ad7d046df0ae27ad620047715b3648bf2ec20dd
|
data/lib/accessory.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
module Accessory; end
|
2
2
|
|
3
3
|
require 'accessory/version'
|
4
|
-
require 'accessory/lens_path'
|
5
4
|
require 'accessory/lens'
|
5
|
+
require 'accessory/bound_lens'
|
6
6
|
require 'accessory/access'
|
7
7
|
|
8
8
|
module Accessory
|
9
9
|
refine ::Object do
|
10
|
-
def lens
|
11
|
-
::Accessory::
|
10
|
+
def lens(...)
|
11
|
+
::Accessory::BoundLens.on(self, ...)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
data/lib/accessory/access.rb
CHANGED
@@ -10,87 +10,102 @@ require 'accessory/accessors/all_accessor'
|
|
10
10
|
require 'accessory/accessors/first_accessor'
|
11
11
|
require 'accessory/accessors/last_accessor'
|
12
12
|
|
13
|
+
##
|
14
|
+
# A set of convenient module-function helpers to use with <tt>Lens[...]</tt>.
|
15
|
+
#
|
16
|
+
# These functions aren't very convenient unless you
|
17
|
+
#
|
18
|
+
# include Accessory
|
19
|
+
|
13
20
|
module Accessory::Access
|
14
|
-
# (see Accessory::SubscriptAccessor)
|
21
|
+
# (see Accessory::Accessors::SubscriptAccessor)
|
15
22
|
def self.subscript(...)
|
16
|
-
Accessory::SubscriptAccessor.new(...)
|
23
|
+
Accessory::Accessors::SubscriptAccessor.new(...)
|
17
24
|
end
|
18
25
|
|
19
|
-
# (see Accessory::AttributeAccessor)
|
26
|
+
# (see Accessory::Accessors::AttributeAccessor)
|
20
27
|
def self.attr(...)
|
21
|
-
Accessory::AttributeAccessor.new(...)
|
28
|
+
Accessory::Accessors::AttributeAccessor.new(...)
|
22
29
|
end
|
23
30
|
|
24
|
-
# (see Accessory::InstanceVariableAccessor)
|
31
|
+
# (see Accessory::Accessors::InstanceVariableAccessor)
|
25
32
|
def self.ivar(...)
|
26
|
-
Accessory::InstanceVariableAccessor.new(...)
|
33
|
+
Accessory::Accessors::InstanceVariableAccessor.new(...)
|
27
34
|
end
|
28
35
|
|
29
|
-
# (see Accessory::BetwixtAccessor)
|
36
|
+
# (see Accessory::Accessors::BetwixtAccessor)
|
30
37
|
def self.betwixt(...)
|
31
|
-
Accessory::BetwixtAccessor.new(...)
|
38
|
+
Accessory::Accessors::BetwixtAccessor.new(...)
|
32
39
|
end
|
33
40
|
|
34
|
-
# Alias for +Accessory::Access.betwixt(0)+. See {Access.betwixt}
|
41
|
+
# Alias for +Accessory::Accessors::Access.betwixt(0)+. See {Access.betwixt}
|
35
42
|
def self.before_first
|
36
43
|
self.betwixt(0)
|
37
44
|
end
|
38
45
|
|
39
|
-
# Alias for +Accessory::Access.betwixt(-1)+. See {Access.betwixt}
|
46
|
+
# Alias for +Accessory::Accessors::Access.betwixt(-1)+. See {Access.betwixt}
|
40
47
|
def self.after_last
|
41
48
|
self.betwixt(-1)
|
42
49
|
end
|
43
50
|
|
44
|
-
# (see Accessory::BetweenEachAccessor)
|
51
|
+
# (see Accessory::Accessors::BetweenEachAccessor)
|
45
52
|
def self.between_each
|
46
|
-
Accessory::BetweenEachAccessor.new
|
53
|
+
Accessory::Accessors::BetweenEachAccessor.new
|
47
54
|
end
|
48
55
|
|
49
|
-
# (see Accessory::AllAccessor)
|
56
|
+
# (see Accessory::Accessors::AllAccessor)
|
50
57
|
def self.all
|
51
|
-
Accessory::AllAccessor.new
|
58
|
+
Accessory::Accessors::AllAccessor.new
|
52
59
|
end
|
53
60
|
|
54
|
-
# (see Accessory::FirstAccessor)
|
61
|
+
# (see Accessory::Accessors::FirstAccessor)
|
55
62
|
def self.first
|
56
|
-
Accessory::FirstAccessor.new
|
63
|
+
Accessory::Accessors::FirstAccessor.new
|
57
64
|
end
|
58
65
|
|
59
|
-
# (see Accessory::LastAccessor)
|
66
|
+
# (see Accessory::Accessors::LastAccessor)
|
60
67
|
def self.last
|
61
|
-
Accessory::LastAccessor.new
|
68
|
+
Accessory::Accessors::LastAccessor.new
|
62
69
|
end
|
63
70
|
|
64
|
-
# (see Accessory::FilterAccessor)
|
71
|
+
# (see Accessory::Accessors::FilterAccessor)
|
65
72
|
def self.filter(&pred)
|
66
|
-
Accessory::FilterAccessor.new(pred)
|
73
|
+
Accessory::Accessors::FilterAccessor.new(pred)
|
67
74
|
end
|
68
75
|
end
|
69
76
|
|
77
|
+
##
|
78
|
+
# A set of convenient "fluent API" builder methods
|
79
|
+
# that get mixed into {Lens} and {BoundLens}.
|
80
|
+
#
|
81
|
+
# These do the same thing as the {Access} helper of the same name, but
|
82
|
+
# wrap the resulting accessor in a call to <tt>#then</tt>, deriving a new
|
83
|
+
# {Lens} or {BoundLens} from the addition of the accessor.
|
84
|
+
|
70
85
|
module Accessory::Access::FluentHelpers
|
71
|
-
# (see Accessory::SubscriptAccessor)
|
86
|
+
# (see Accessory::Accessors::SubscriptAccessor)
|
72
87
|
def subscript(...)
|
73
|
-
self.then(Accessory::SubscriptAccessor.new(...))
|
88
|
+
self.then(Accessory::Accessors::SubscriptAccessor.new(...))
|
74
89
|
end
|
75
90
|
|
76
91
|
# Alias for {#subscript}
|
77
92
|
def [](...)
|
78
|
-
self.then(Accessory::SubscriptAccessor.new(...))
|
93
|
+
self.then(Accessory::Accessors::SubscriptAccessor.new(...))
|
79
94
|
end
|
80
95
|
|
81
|
-
# (see Accessory::AttributeAccessor)
|
96
|
+
# (see Accessory::Accessors::AttributeAccessor)
|
82
97
|
def attr(...)
|
83
|
-
self.then(Accessory::AttributeAccessor.new(...))
|
98
|
+
self.then(Accessory::Accessors::AttributeAccessor.new(...))
|
84
99
|
end
|
85
100
|
|
86
|
-
# (see Accessory::InstanceVariableAccessor)
|
101
|
+
# (see Accessory::Accessors::InstanceVariableAccessor)
|
87
102
|
def ivar(...)
|
88
|
-
self.then(Accessory::InstanceVariableAccessor.new(...))
|
103
|
+
self.then(Accessory::Accessors::InstanceVariableAccessor.new(...))
|
89
104
|
end
|
90
105
|
|
91
|
-
# (see Accessory::BetwixtAccessor)
|
106
|
+
# (see Accessory::Accessors::BetwixtAccessor)
|
92
107
|
def betwixt(...)
|
93
|
-
self.then(Accessory::BetwixtAccessor.new(...))
|
108
|
+
self.then(Accessory::Accessors::BetwixtAccessor.new(...))
|
94
109
|
end
|
95
110
|
|
96
111
|
# Alias for +#betwixt(0)+. See {#betwixt}
|
@@ -103,29 +118,29 @@ module Accessory::Access::FluentHelpers
|
|
103
118
|
self.betwixt(-1)
|
104
119
|
end
|
105
120
|
|
106
|
-
# (see Accessory::BetweenEachAccessor)
|
121
|
+
# (see Accessory::Accessors::BetweenEachAccessor)
|
107
122
|
def between_each
|
108
|
-
self.then(Accessory::BetweenEachAccessor.new)
|
123
|
+
self.then(Accessory::Accessors::BetweenEachAccessor.new)
|
109
124
|
end
|
110
125
|
|
111
|
-
# (see Accessory::AllAccessor)
|
126
|
+
# (see Accessory::Accessors::AllAccessor)
|
112
127
|
def all
|
113
|
-
self.then(Accessory::AllAccessor.new)
|
128
|
+
self.then(Accessory::Accessors::AllAccessor.new)
|
114
129
|
end
|
115
130
|
|
116
|
-
# (see Accessory::FirstAccessor)
|
131
|
+
# (see Accessory::Accessors::FirstAccessor)
|
117
132
|
def first
|
118
|
-
self.then(Accessory::FirstAccessor.new)
|
133
|
+
self.then(Accessory::Accessors::FirstAccessor.new)
|
119
134
|
end
|
120
135
|
|
121
|
-
# (see Accessory::LastAccessor)
|
136
|
+
# (see Accessory::Accessors::LastAccessor)
|
122
137
|
def last
|
123
|
-
self.then(Accessory::LastAccessor.new)
|
138
|
+
self.then(Accessory::Accessors::LastAccessor.new)
|
124
139
|
end
|
125
140
|
|
126
|
-
# (see Accessory::FilterAccessor)
|
141
|
+
# (see Accessory::Accessors::FilterAccessor)
|
127
142
|
def filter(&pred)
|
128
|
-
self.then(Accessory::FilterAccessor.new(pred))
|
143
|
+
self.then(Accessory::Accessors::FilterAccessor.new(pred))
|
129
144
|
end
|
130
145
|
end
|
131
146
|
|
@@ -133,6 +148,6 @@ class Accessory::Lens
|
|
133
148
|
include Accessory::Access::FluentHelpers
|
134
149
|
end
|
135
150
|
|
136
|
-
class Accessory::
|
151
|
+
class Accessory::BoundLens
|
137
152
|
include Accessory::Access::FluentHelpers
|
138
153
|
end
|
data/lib/accessory/accessor.rb
CHANGED
@@ -1,19 +1,33 @@
|
|
1
1
|
module Accessory; end
|
2
2
|
|
3
3
|
##
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
# The parent class for accessors. Contains some shared behavior all accessors
|
5
|
+
# can rely on.
|
6
|
+
#
|
7
|
+
# It doesn't make sense to instantiate this class directly. Instantiate specific
|
8
|
+
# {Accessor} subclasses instead.
|
9
|
+
#
|
10
|
+
# == Implementing an Accessor
|
11
|
+
#
|
12
|
+
# To implement an {Accessor} subclass, you must define at minimum these two
|
13
|
+
# methods (see the method docs of these methods for details):
|
14
|
+
#
|
15
|
+
# * {Accessor#get}
|
16
|
+
# * {Accessor#get_and_update}
|
17
|
+
#
|
18
|
+
# You may also implement these two methods (again, see method docs for more
|
19
|
+
# info):
|
20
|
+
#
|
21
|
+
# * {Accessor#traverse}
|
22
|
+
# * {Accessor#ensure_valid}
|
9
23
|
|
10
|
-
|
24
|
+
class Accessory::Accessor
|
11
25
|
TERMINAL_DEFAULT_FN = lambda{ nil }
|
26
|
+
private_constant :TERMINAL_DEFAULT_FN
|
12
27
|
|
13
28
|
# @!visibility private
|
14
|
-
def initialize(
|
15
|
-
@default_value =
|
16
|
-
@make_default_fn = TERMINAL_DEFAULT_FN
|
29
|
+
def initialize(default_value = nil)
|
30
|
+
@default_value = default_value
|
17
31
|
end
|
18
32
|
|
19
33
|
# @!visibility private
|
@@ -40,7 +54,10 @@ class Accessory::Accessor
|
|
40
54
|
end
|
41
55
|
|
42
56
|
# @!visibility private
|
43
|
-
HIDDEN_IVARS = [:@default_value, :@
|
57
|
+
HIDDEN_IVARS = [:@default_value, :@successor]
|
58
|
+
private_constant :HIDDEN_IVARS
|
59
|
+
|
60
|
+
# @!visibility private
|
44
61
|
def inspect_args
|
45
62
|
(instance_variables - HIDDEN_IVARS).map do |ivar_k|
|
46
63
|
ivar_v = instance_variable_get(ivar_k)
|
@@ -49,19 +66,151 @@ class Accessory::Accessor
|
|
49
66
|
end
|
50
67
|
|
51
68
|
# @!visibility private
|
52
|
-
attr_accessor :
|
69
|
+
attr_accessor :successor
|
53
70
|
|
54
|
-
# @!
|
55
|
-
def value_or_default(data)
|
56
|
-
return nil if data.nil?
|
71
|
+
# @!group Helpers
|
57
72
|
|
58
|
-
|
59
|
-
|
73
|
+
# Safely traverses +data+, with useful defaults; simplifies implementations of
|
74
|
+
# {get} and {get_and_update}.
|
75
|
+
#
|
76
|
+
# Rather than writing redundant traversal logic into both methods, you can
|
77
|
+
# implement the callback method {traverse} to define your traversal, and then
|
78
|
+
# call <tt>traverse_or_default(data)</tt> within your implementation to safely
|
79
|
+
# get a traversal-result to operate on.
|
80
|
+
#
|
81
|
+
# The value returned by your {traverse} callback will be validated by your
|
82
|
+
# calling the {ensure_valid} callback of the _successor accessor_ in the Lens
|
83
|
+
# path. {ensure_valid} will replace any value it considers invalid with a
|
84
|
+
# reasonable default. This means you don't need to worry about what will
|
85
|
+
# happen if your traversal doesn't find a value and so returns +nil+. The
|
86
|
+
# successor's {ensure_valid} will replace that +nil+ with a value that works
|
87
|
+
# for it.
|
88
|
+
def traverse_or_default(data)
|
89
|
+
traversal_result = traverse(data) || @default_value
|
60
90
|
|
61
|
-
if
|
62
|
-
@
|
91
|
+
if @successor
|
92
|
+
@successor.ensure_valid(traversal_result)
|
63
93
|
else
|
64
|
-
|
94
|
+
traversal_result
|
65
95
|
end
|
66
96
|
end
|
97
|
+
|
98
|
+
# @!endgroup
|
99
|
+
|
100
|
+
# Traverses +data+ in some way, and feeds the result of the traversal to the
|
101
|
+
# next step in the accessor chain by yielding the traversal-result to the
|
102
|
+
# passed-in block +succ+. The result from the yield is the result coming from
|
103
|
+
# the end of the accessor chain. Usually, it should be returned as-is.
|
104
|
+
#
|
105
|
+
# +succ+ can be yielded to multiple times, to run the rest of the accessor
|
106
|
+
# chain against multiple parts of +data+. In this case, the yield results
|
107
|
+
# should be gathered up into some container object to be returned together.
|
108
|
+
#
|
109
|
+
# The successor accessor will receive the yielded element as its +data+.
|
110
|
+
#
|
111
|
+
# After returning, the predecessor accessor will receive the result returned
|
112
|
+
# from {get} as the result of its own +yield+.
|
113
|
+
#
|
114
|
+
# @param data [Enumerable] the data yielded by the predecessor accessor.
|
115
|
+
# @param succ [Proc] a thunk to the successor accessor. When {get} is called
|
116
|
+
# by a {Lens}, this is passed implicitly.
|
117
|
+
# @return [Object] the data to pass back to the predecessor accessor as a
|
118
|
+
# yield result.
|
119
|
+
def get(data, &succ)
|
120
|
+
raise NotImplementedError, "Accessor subclass #{self.class} must implement #get"
|
121
|
+
end
|
122
|
+
|
123
|
+
# Traverses +data+ in some way, and feeds the result of the traversal to the
|
124
|
+
# next step in the accessor chain by yielding the traversal-result to the
|
125
|
+
# passed-in block +succ+.
|
126
|
+
#
|
127
|
+
# The result of the yield will be a "modification command", one of these two:
|
128
|
+
# * an *update command* <tt>[get_result, new_value]</tt>
|
129
|
+
# * the symbol <tt>:pop</tt>
|
130
|
+
#
|
131
|
+
# In the *update command* case:
|
132
|
+
# * the +get_result+ should be returned as-is (or gathered together into
|
133
|
+
# a container object if this accessor yields multiple times.) The data flow
|
134
|
+
# of the +get_result+s should replicate the data flow of {get}.
|
135
|
+
# * the +new_value+ should be used to *replace* or *overwrite* the result of
|
136
|
+
# this accessor's traversal within +data+. For example, in
|
137
|
+
# {Accessors::SubscriptAccessor}, <tt>data[key] = new_value</tt> is
|
138
|
+
# executed.
|
139
|
+
#
|
140
|
+
# In the <tt>:pop</tt> command case:
|
141
|
+
# * the result of the traversal (*before* the yield) should be returned. This
|
142
|
+
# implies that any {get_and_update} implementation must capture its
|
143
|
+
# traversal-results before feeding them into yield, in order to return them
|
144
|
+
# here.
|
145
|
+
# * the traversal-result should be *removed* from +data+. For example, in
|
146
|
+
# {Accessors::SubscriptAccessor}, <tt>data.delete(key)</tt> is executed.
|
147
|
+
#
|
148
|
+
# The successor in the accessor chain will receive the yielded
|
149
|
+
# traversal-results as its own +data+.
|
150
|
+
#
|
151
|
+
# After returning, the predecessor accessor will receive the result returned
|
152
|
+
# from this method as the result of its own +yield+. This implies that
|
153
|
+
# this method should almost always be implemented to *return* an update
|
154
|
+
# command, looking like one of the following:
|
155
|
+
#
|
156
|
+
# # given [get_result, new_value]
|
157
|
+
# [get_result, data_after_update]
|
158
|
+
#
|
159
|
+
# # given :pop
|
160
|
+
# [traversal_result, data_after_removal]
|
161
|
+
#
|
162
|
+
# @param data [Enumerable] the data yielded by the predecessor accessor.
|
163
|
+
# @param succ [Proc] a thunk to the successor accessor. When {get} is called
|
164
|
+
# by a {Lens}, this is passed implicitly.
|
165
|
+
# @return [Object] the modification-command to pass back to the predecessor
|
166
|
+
# accessor as a yield result.
|
167
|
+
def get_and_update(data, &succ)
|
168
|
+
raise NotImplementedError, "Accessor subclass #{self.class} must implement #get_and_update"
|
169
|
+
end
|
170
|
+
|
171
|
+
# @!group Callbacks
|
172
|
+
|
173
|
+
# Traverses +data+; called by {traverse_or_default}.
|
174
|
+
#
|
175
|
+
# This method should traverse +data+ however your accessor does that,
|
176
|
+
# producing either one traversal-result or a container-object of gathered
|
177
|
+
# traversal-results.
|
178
|
+
#
|
179
|
+
# This method can assume that +data+ is a valid receiver for the traversal
|
180
|
+
# it performs. {traverse_or_default} takes care of feeding in a default +data+
|
181
|
+
# in the case where the predecessor passed invalid data.
|
182
|
+
#
|
183
|
+
# @param data [Object] the object to be traversed
|
184
|
+
# @return [Object] the result of traversal
|
185
|
+
def traverse(data)
|
186
|
+
raise NotImplementedError, "Accessor subclass #{self.class} must implement #traverse to use #traverse_or_default"
|
187
|
+
end
|
188
|
+
|
189
|
+
# Ensures that the predecessor accessor's traversal result is one this
|
190
|
+
# accessor can operate on; called by {traverse_or_default}.
|
191
|
+
#
|
192
|
+
# This callback should validate that the +traversal_result+ is one that can
|
193
|
+
# be traversed by the traversal-method of this accessor. If it can, the
|
194
|
+
# +traversal_result+ should be returned unchanged. If it cannot, an object
|
195
|
+
# that _can_ be traversed should be returned instead.
|
196
|
+
#
|
197
|
+
#
|
198
|
+
# For example, if your accessor operates on +Enumerable+ values (like
|
199
|
+
# {Accessors::AllAccessor}), then this method should validate that the
|
200
|
+
# +traversal_result+ is +Enumerable+; and, if it isn't, return something that
|
201
|
+
# is — e.g. an empty +Array+.
|
202
|
+
#
|
203
|
+
# This logic is used to replace invalid intermediate values (e.g. `nil`s and
|
204
|
+
# scalars) with containers during {Lens#put_in} et al.
|
205
|
+
#
|
206
|
+
# @return [Object] a now-valid traversal result
|
207
|
+
def ensure_valid(traversal_result)
|
208
|
+
lambda do
|
209
|
+
raise NotImplementedError, "Accessor subclass #{self.class} must implement #ensure_valid to allow chain-predecessor to use #traverse_or_default"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# @!endgroup
|
67
214
|
end
|
215
|
+
|
216
|
+
module Accessory::Accessors; end
|
@@ -5,7 +5,7 @@ require 'accessory/accessor'
|
|
5
5
|
#
|
6
6
|
# *Aliases*
|
7
7
|
# * {Access.all}
|
8
|
-
# * {Access::FluentHelpers#all} (included in {
|
8
|
+
# * {Access::FluentHelpers#all} (included in {Lens} and {BoundLens})
|
9
9
|
#
|
10
10
|
# *Equivalents* in Elixir's {https://hexdocs.pm/elixir/Access.html +Access+} module
|
11
11
|
# * {https://hexdocs.pm/elixir/Access.html#all/0 +Access.all/0+}
|
@@ -15,10 +15,14 @@ require 'accessory/accessor'
|
|
15
15
|
#
|
16
16
|
# * +Array.new+
|
17
17
|
|
18
|
-
class Accessory::AllAccessor < Accessory::Accessor
|
18
|
+
class Accessory::Accessors::AllAccessor < Accessory::Accessor
|
19
19
|
# @!visibility private
|
20
|
-
def
|
21
|
-
|
20
|
+
def ensure_valid(traversal_result)
|
21
|
+
if traversal_result.kind_of?(Enumerable)
|
22
|
+
traversal_result
|
23
|
+
else
|
24
|
+
[]
|
25
|
+
end
|
22
26
|
end
|
23
27
|
|
24
28
|
# @!visibility private
|
@@ -46,17 +50,28 @@ class Accessory::AllAccessor < Accessory::Accessor
|
|
46
50
|
def get_and_update(data)
|
47
51
|
results = []
|
48
52
|
new_data = []
|
53
|
+
dirty = false
|
49
54
|
|
50
55
|
(data || []).each do |pos|
|
51
56
|
case yield(pos)
|
52
|
-
in [result,
|
57
|
+
in [:clean, result, _]
|
58
|
+
results.push(result)
|
59
|
+
new_data.push(pos)
|
60
|
+
# ok
|
61
|
+
in [:dirty, result, new_value]
|
53
62
|
results.push(result)
|
54
63
|
new_data.push(new_value)
|
64
|
+
dirty = true
|
55
65
|
in :pop
|
56
66
|
results.push(pos)
|
67
|
+
dirty = true
|
57
68
|
end
|
58
69
|
end
|
59
70
|
|
60
|
-
|
71
|
+
if dirty
|
72
|
+
[:dirty, results, new_data]
|
73
|
+
else
|
74
|
+
[:clean, results, data]
|
75
|
+
end
|
61
76
|
end
|
62
77
|
end
|