ryo.rb 0.5.5 → 0.5.7
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/.github/workflows/specs.yml +2 -2
- data/.rubocop.yml +2 -0
- data/README.md +46 -27
- data/lib/ryo/basic_object.rb +7 -11
- data/lib/ryo/builder.rb +35 -54
- data/lib/ryo/enumerable.rb +62 -79
- data/lib/ryo/json.rb +6 -11
- data/lib/ryo/keywords.rb +16 -28
- data/lib/ryo/object.rb +6 -10
- data/lib/ryo/reflect.rb +54 -170
- data/lib/ryo/utils.rb +68 -0
- data/lib/ryo/version.rb +1 -1
- data/lib/ryo/yaml.rb +6 -11
- data/lib/ryo.rb +26 -37
- data/ryo.rb.gemspec +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/1.0_prototypes_point_object.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/1.1_prototypes_ryo_fn.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/2.0_iteration_each.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/2.1_iteration_map.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/2.2_iteration_ancestors.rb +1 -0
- data/share/examples/ryo.rb/3.0_recursion_ryo_from.rb +20 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/3.1_recursion_ryo_from_with_array.rb +5 -4
- data/share/{ryo.rb/examples → examples/ryo.rb}/3.2_recursion_ryo_from_with_openstruct.rb +3 -3
- data/share/{ryo.rb/examples → examples/ryo.rb}/4.0_basicobject_ryo_basicobject.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/4.1_basicobject_ryo_basicobject_from.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/5_collisions_resolution_strategy.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/6_beyond_hash_objects.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/7_ryo_memo.rb +1 -0
- data/share/ryo.rb/NEWS +11 -0
- data/spec/readme_spec.rb +2 -2
- data/spec/ryo_enumerable_spec.rb +1 -1
- data/spec/ryo_json_spec.rb +1 -1
- data/spec/ryo_keywords_spec.rb +1 -1
- data/spec/ryo_prototypes_spec.rb +1 -1
- data/spec/ryo_reflect_spec.rb +8 -0
- data/spec/ryo_spec.rb +1 -1
- data/spec/ryo_yaml_spec.rb +1 -1
- metadata +34 -18
- data/share/ryo.rb/examples/3.0_recursion_ryo_from.rb +0 -13
- /data/share/{ryo.rb/examples → examples/ryo.rb}/setup.rb +0 -0
- /data/{LICENSE → share/ryo.rb/LICENSE} +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbd00dab052b65ba426cdaa4ac900adc2daca2e23d1cbe5919a19e31bce30e45
|
4
|
+
data.tar.gz: 6757fd8be13568acb58fa6e0e5ec3ff395ab56bb14354dd6bbd024665998ff1d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 13896d019d82fdb27003ead6dd60a34a8f2c09efb2aa018b74f520d8dbc5c79e775d5637ba66e715089221aad160dc7a00477cd0a908777ed9e5098c8eccf552
|
7
|
+
data.tar.gz: 3bfc72a7632226f9b67899045869fbec25a505276d5d595c5f13dc7a288924a4510d1b5e7ec69c120bff981fae887684953e6a223e481920dbf77d880c3448d1
|
data/.github/workflows/specs.yml
CHANGED
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -16,6 +16,7 @@ method seen in the example returns an instance of
|
|
16
16
|
[Ryo::Object](https://0x1eef.github.io/x/ryo.rb/Ryo/Object.html):
|
17
17
|
|
18
18
|
```ruby
|
19
|
+
#!/usr/bin/env ruby
|
19
20
|
require "ryo"
|
20
21
|
|
21
22
|
point_x = Ryo(x: 5)
|
@@ -35,6 +36,7 @@ will bind its `self` to the Ryo object it is assigned to, and when the function
|
|
35
36
|
is called it will have access to the properties of the Ryo object:
|
36
37
|
|
37
38
|
```ruby
|
39
|
+
#!/usr/bin/env ruby
|
38
40
|
require "ryo"
|
39
41
|
|
40
42
|
point_x = Ryo(x: 5)
|
@@ -56,6 +58,7 @@ The following example demonstrates
|
|
56
58
|
accessed for the first time. It is similar to a Ryo function:
|
57
59
|
|
58
60
|
```ruby
|
61
|
+
#!/usr/bin/env ruby
|
59
62
|
require "ryo"
|
60
63
|
|
61
64
|
point_x = Ryo(x: Ryo.memo { 5 })
|
@@ -87,6 +90,7 @@ is not implemented directly on a Ryo object.
|
|
87
90
|
A demonstration of [`Ryo.each`](https://0x1eef.github.io/x/ryo.rb/Ryo.html#each-class_method):
|
88
91
|
|
89
92
|
```ruby
|
93
|
+
#!/usr/bin/env ruby
|
90
94
|
require "ryo"
|
91
95
|
|
92
96
|
point = Ryo(x: 10, y: 20)
|
@@ -115,6 +119,7 @@ and it returns a new copy of a Ryo object and its prototypes.
|
|
115
119
|
A demonstration of [`Ryo.map!`](http://0x1eef.github.io/x/ryo.rb/Ryo/Enumerable.html#map!-instance_method):
|
116
120
|
|
117
121
|
```ruby
|
122
|
+
#!/usr/bin/env ruby
|
118
123
|
require "ryo"
|
119
124
|
|
120
125
|
point_x = Ryo(x: 2)
|
@@ -148,6 +153,7 @@ demonstrates using the `ancestors` option with
|
|
148
153
|
[`Ryo.find`](https://0x1eef.github.io/x/ryo.rb/Ryo.html#find-class_method):
|
149
154
|
|
150
155
|
```ruby
|
156
|
+
#!/usr/bin/env ruby
|
151
157
|
require "ryo"
|
152
158
|
|
153
159
|
point_x = Ryo(x: 5)
|
@@ -167,23 +173,28 @@ p Ryo.find(point) { |k,v| v == 5 }.x # => point_x.x
|
|
167
173
|
The [`Ryo.from`](https://0x1eef.github.io/x/ryo.rb/Ryo.html#from-class_method) method has
|
168
174
|
the same interface as the [`Ryo`](https://0x1eef.github.io/x/ryo.rb/top-level-namespace.html#Ryo-instance_method)
|
169
175
|
method, but it is implemented to recursively walk a Hash object and create Ryo objects
|
170
|
-
from other Hash objects found along the way.
|
171
|
-
because it has the potential to be slow when given a complex Hash object that's
|
172
|
-
very large - otherwise there shouldn't be a noticeable performance impact.
|
176
|
+
from other Hash objects found along the way.
|
173
177
|
|
174
178
|
The following example demonstrates [`Ryo.from`](https://0x1eef.github.io/x/ryo.rb/Ryo.html#from-class_method):
|
175
179
|
|
176
180
|
```ruby
|
181
|
+
#!/usr/bin/env ruby
|
177
182
|
require "ryo"
|
178
183
|
|
179
|
-
|
180
|
-
|
181
|
-
|
184
|
+
person = Ryo.from({
|
185
|
+
name: "John",
|
186
|
+
age: 30,
|
187
|
+
address: {
|
188
|
+
street: "123 Main St",
|
189
|
+
city: "Anytown",
|
190
|
+
state: "AS",
|
191
|
+
zip: 12345
|
192
|
+
}
|
182
193
|
})
|
183
|
-
p [
|
194
|
+
p [person.name, person.age, person.address.city]
|
184
195
|
|
185
196
|
##
|
186
|
-
# [
|
197
|
+
# ["John", 30, "Anytown"]
|
187
198
|
```
|
188
199
|
|
189
200
|
#### Ryo.from with an Array
|
@@ -194,17 +205,18 @@ An object that can't be turned into a Ryo object is left as-is. The following
|
|
194
205
|
example demonstrates how that works in practice:
|
195
206
|
|
196
207
|
``` ruby
|
208
|
+
#!/usr/bin/env ruby
|
197
209
|
require "ryo"
|
198
210
|
|
199
211
|
points = Ryo.from([
|
200
|
-
{x:
|
212
|
+
{x: 2},
|
201
213
|
"foobar",
|
202
|
-
{y:
|
214
|
+
{y: 4}
|
203
215
|
])
|
204
216
|
|
205
|
-
p points[0].x
|
217
|
+
p points[0].x
|
206
218
|
p points[1]
|
207
|
-
p points[2].y
|
219
|
+
p points[2].y
|
208
220
|
|
209
221
|
##
|
210
222
|
# 2
|
@@ -217,18 +229,17 @@ p points[2].y.to_i
|
|
217
229
|
All methods that can create Ryo objects support turning a Struct, or OpenStruct object
|
218
230
|
into a Ryo object. The following example demonstrates how
|
219
231
|
[`Ryo.from`](https://0x1eef.github.io/x/ryo.rb/Ryo.html#from-class_method)
|
220
|
-
can recursively turn an OpenStruct object into Ryo objects
|
221
|
-
a prototype to the Ryo object created from the OpenStruct:
|
232
|
+
can recursively turn an OpenStruct object into Ryo objects:
|
222
233
|
|
223
234
|
``` ruby
|
235
|
+
#!/usr/bin/env ruby
|
224
236
|
require "ryo"
|
225
237
|
require "ostruct"
|
226
238
|
|
227
239
|
point = Ryo.from(
|
228
|
-
OpenStruct.new(x:
|
229
|
-
Ryo.from(y: {to_i: 10})
|
240
|
+
OpenStruct.new(x: 5, y: 10)
|
230
241
|
)
|
231
|
-
p [point.x
|
242
|
+
p [point.x, point.y]
|
232
243
|
|
233
244
|
##
|
234
245
|
# [5, 10]
|
@@ -246,6 +257,7 @@ with fewer methods. The following example demonstrates
|
|
246
257
|
how to create an instance of [Ryo::BasicObject](https://0x1eef.github.io/x/ryo.rb/Ryo/BasicObject.html):
|
247
258
|
|
248
259
|
```ruby
|
260
|
+
#!/usr/bin/env ruby
|
249
261
|
require "ryo"
|
250
262
|
|
251
263
|
point_x = Ryo::BasicObject(x: 0)
|
@@ -265,6 +277,7 @@ it returns instance(s) of [Ryo::BasicObject](https://0x1eef.github.io/x/ryo.rb/R
|
|
265
277
|
instead:
|
266
278
|
|
267
279
|
```ruby
|
280
|
+
#!/usr/bin/env ruby
|
268
281
|
require "ryo"
|
269
282
|
|
270
283
|
point = Ryo::BasicObject.from({
|
@@ -281,18 +294,21 @@ p [point.x.to_i, point.y.to_i]
|
|
281
294
|
|
282
295
|
#### Resolution strategy
|
283
296
|
|
284
|
-
When a property and method collide, Ryo tries to
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
297
|
+
When a property and method collide, Ryo tries to
|
298
|
+
find the best resolution. Because Ryo properties don't
|
299
|
+
accept arguments, and methods can - we can distinguish a
|
300
|
+
method from a Ryo property by the presence or absence of
|
301
|
+
an argument in at least some cases. Consider the following
|
302
|
+
example, where a property collides with the `Kernel#then` method:
|
290
303
|
|
291
304
|
```ruby
|
305
|
+
#!/usr/bin/env ruby
|
292
306
|
require "ryo"
|
293
307
|
|
294
308
|
ryo = Ryo::Object(then: 12)
|
309
|
+
# Resolves to Ryo property
|
295
310
|
p ryo.then # => 12
|
311
|
+
# Resolves to Kernel#then
|
296
312
|
p ryo.then { 34 } # => 34
|
297
313
|
```
|
298
314
|
|
@@ -300,10 +316,12 @@ p ryo.then { 34 } # => 34
|
|
300
316
|
|
301
317
|
#### Duck typing
|
302
318
|
|
303
|
-
The documentation has used simple terms to describe
|
304
|
-
with: Hash and Array objects.
|
305
|
-
|
306
|
-
|
319
|
+
The documentation has used simple terms to describe
|
320
|
+
the objects that Ryo works with: Hash and Array objects.
|
321
|
+
But that doesn't quite capture that Ryo is implemented with
|
322
|
+
duck typing: any object that implements `#each_pair`
|
323
|
+
could be used instead of a Hash, and any object that
|
324
|
+
implements `#each` could be used instead of an Array. Note that only
|
307
325
|
[Ryo.from](https://0x1eef.github.io/x/ryo.rb/Ryo.html#from-class_method),
|
308
326
|
[Ryo::Object.from](https://0x1eef.github.io/x/ryo.rb/Ryo/Object.html#from-class_method)
|
309
327
|
and
|
@@ -313,6 +331,7 @@ can handle Array-like objects.
|
|
313
331
|
The following example implements `#each_pair`:
|
314
332
|
|
315
333
|
``` ruby
|
334
|
+
#!/usr/bin/env ruby
|
316
335
|
require "ryo"
|
317
336
|
|
318
337
|
class Point
|
data/lib/ryo/basic_object.rb
CHANGED
@@ -10,33 +10,30 @@ class Ryo::BasicObject < BasicObject
|
|
10
10
|
##
|
11
11
|
# @param props (see Ryo::Builder.build)
|
12
12
|
# @param prototype (see Ryo::Builder.build)
|
13
|
-
#
|
14
13
|
# @return [Ryo::BasicObject]
|
15
|
-
# Returns an instance of {Ryo::BasicObject Ryo::BasicObject}
|
14
|
+
# Returns an instance of {Ryo::BasicObject Ryo::BasicObject}
|
16
15
|
def self.create(props, prototype = nil)
|
17
16
|
::Ryo::Builder.build(self, props, prototype)
|
18
17
|
end
|
19
18
|
|
20
19
|
##
|
21
|
-
# Creates a Ryo object by recursively walking a Hash object
|
20
|
+
# Creates a Ryo object by recursively walking a Hash object
|
22
21
|
#
|
23
22
|
# @param props (see Ryo::Builder.recursive_build)
|
24
23
|
# @param prototype (see Ryo::Builder.recursive_build)
|
25
|
-
#
|
26
24
|
# @return [Ryo::BasicObject]
|
27
|
-
# Returns an instance of {Ryo::BasicObject Ryo::BasicObject}
|
25
|
+
# Returns an instance of {Ryo::BasicObject Ryo::BasicObject}
|
28
26
|
def self.from(props, prototype = nil)
|
29
27
|
::Ryo::Builder.recursive_build(self, props, prototype)
|
30
28
|
end
|
31
29
|
|
32
30
|
##
|
33
|
-
# Duplicates the internals of a Ryo object
|
31
|
+
# Duplicates the internals of a Ryo object
|
34
32
|
#
|
35
33
|
# @param [Ryo::BasicObject] ryo
|
36
|
-
# A Ryo object
|
37
|
-
#
|
34
|
+
# A Ryo object
|
38
35
|
# @return [Ryo::BasicObject]
|
39
|
-
# Returns a Ryo object
|
36
|
+
# Returns a Ryo object
|
40
37
|
def initialize_dup(ryo)
|
41
38
|
::Ryo.set_table_of(self, ::Ryo.table_of(ryo).dup)
|
42
39
|
::Ryo.extend!(self, ::Ryo)
|
@@ -50,9 +47,8 @@ end
|
|
50
47
|
#
|
51
48
|
# @param props (see Ryo::Builder.build)
|
52
49
|
# @param prototype (see Ryo::Builder.build)
|
53
|
-
#
|
54
50
|
# @return [Ryo::BasicObject]
|
55
|
-
# Returns an instance of {Ryo::BasicObject Ryo::BasicObject}
|
51
|
+
# Returns an instance of {Ryo::BasicObject Ryo::BasicObject}
|
56
52
|
def Ryo.BasicObject(props, prototype = nil)
|
57
53
|
Ryo::BasicObject.create(props, prototype)
|
58
54
|
end
|
data/lib/ryo/builder.rb
CHANGED
@@ -1,29 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
##
|
4
|
-
# {Ryo::Builder Ryo::Builder}
|
5
|
-
#
|
6
|
-
# {Ryo::BasicObject Ryo::BasicObject}. This module is
|
7
|
-
# used directly.
|
8
|
-
#
|
4
|
+
# The {Ryo::Builder Ryo::Builder} module is responsible for
|
5
|
+
# the creation of instances of {Ryo::Object Ryo::Object},
|
6
|
+
# and {Ryo::BasicObject Ryo::BasicObject}. This module is
|
7
|
+
# not intended to be used directly.
|
9
8
|
# @api private
|
10
9
|
module Ryo::Builder
|
11
10
|
##
|
11
|
+
# @note
|
12
|
+
# When "props" is given as a Ryo object, a duplicate Ryo object is
|
13
|
+
# returned in its place
|
12
14
|
# @param [<Ryo::Object, Ryo::BasicObject>] buildee
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# @param [<Hash, Ryo::Object, Ryo::BasicObject, #each_pair>] props
|
16
|
-
# A Hash object, an object that implements "#each_pair", or a Ryo object.
|
17
|
-
#
|
15
|
+
# @param [<#each_pair>] props
|
18
16
|
# @param [<Ryo::Object, Ryo::BasicObject>, nil] prototype
|
19
|
-
# The prototype, or nil for none.
|
20
|
-
#
|
21
17
|
# @return [<Ryo::Object, Ryo::BasicObject>]
|
22
|
-
# Returns a Ryo object
|
23
|
-
#
|
24
|
-
# @note
|
25
|
-
# When "props" is given as a Ryo object, a duplicate Ryo object is
|
26
|
-
# returned in its place.
|
18
|
+
# Returns a Ryo object
|
27
19
|
def self.build(buildee, props, prototype = nil)
|
28
20
|
if Ryo.ryo?(props)
|
29
21
|
build(buildee, Ryo.table_of(props), prototype || Ryo.prototype_of(props))
|
@@ -38,7 +30,8 @@ module Ryo::Builder
|
|
38
30
|
end
|
39
31
|
|
40
32
|
##
|
41
|
-
# Creates a Ryo object by recursively walking a Hash object, or
|
33
|
+
# Creates a Ryo object by recursively walking a Hash object, or
|
34
|
+
# an Array of Hash objects
|
42
35
|
#
|
43
36
|
# @example
|
44
37
|
# objects = Ryo.from([{x: 0, y: 0}, "foo", {point: {x: 0, y: 0}}])
|
@@ -46,22 +39,13 @@ module Ryo::Builder
|
|
46
39
|
# objects[1] # => "foo"
|
47
40
|
# objects[2].point.x # => 0
|
48
41
|
#
|
49
|
-
# @
|
50
|
-
#
|
51
|
-
# @param [<Hash, Ryo::Object, Ryo::BasicObject, Array, #each_pair, #each> ] props
|
52
|
-
# A Hash object, a Ryo object, or an array composed of either Hash / Ryo objects.
|
53
|
-
#
|
54
|
-
# @param prototype (see Ryo::Builder.build)
|
55
|
-
#
|
42
|
+
# @note (see Ryo::Builder.build)
|
43
|
+
# @param (see Ryo::Builder.build)
|
56
44
|
# @return (see Ryo::Builder.build)
|
57
|
-
#
|
58
|
-
# @note
|
59
|
-
# When "props" is given as a Ryo object, a duplicate Ryo object is
|
60
|
-
# returned in its place.
|
61
45
|
def self.recursive_build(buildee, props, prototype = nil)
|
62
46
|
if Ryo.ryo?(props)
|
63
47
|
recursive_build(buildee, Ryo.table_of(props), prototype || Ryo.prototype_of(props))
|
64
|
-
elsif
|
48
|
+
elsif !respond_to_each?(props)
|
65
49
|
raise TypeError, "The provided object does not implement #each / #each_pair"
|
66
50
|
elsif !props.respond_to?(:each_pair)
|
67
51
|
map(props) do
|
@@ -75,32 +59,29 @@ module Ryo::Builder
|
|
75
59
|
end
|
76
60
|
end
|
77
61
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
value
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
62
|
+
module Private
|
63
|
+
private
|
64
|
+
|
65
|
+
def map_value(buildee, value)
|
66
|
+
if Ryo.ryo?(value) || !respond_to_each?(value)
|
67
|
+
value
|
68
|
+
elsif value.respond_to?(:each_pair)
|
69
|
+
recursive_build(buildee, value)
|
70
|
+
elsif value.respond_to?(:each)
|
71
|
+
map(value) { map_value(buildee, _1) }
|
72
|
+
end
|
87
73
|
end
|
88
|
-
end
|
89
|
-
private_class_method :map_value
|
90
74
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
!value.respond_to?(:each) && !value.respond_to?(:each_pair)
|
95
|
-
end
|
96
|
-
private_class_method :eachless?
|
75
|
+
def respond_to_each?(value)
|
76
|
+
value.respond_to?(:each) || value.respond_to?(:each_pair)
|
77
|
+
end
|
97
78
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
ary
|
79
|
+
def map(obj)
|
80
|
+
ary = []
|
81
|
+
obj.each { ary.push(yield(_1)) }
|
82
|
+
ary
|
83
|
+
end
|
104
84
|
end
|
105
|
-
|
85
|
+
private_constant :Private
|
86
|
+
extend Private
|
106
87
|
end
|
data/lib/ryo/enumerable.rb
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
##
|
4
|
-
# The {Ryo::Enumerable Ryo::Enumerable} module
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
4
|
+
# The {Ryo::Enumerable Ryo::Enumerable} module provides methods
|
5
|
+
# that are similar to Ruby's Enumerable module, and at the same
|
6
|
+
# time - intentionally different.
|
7
|
+
#
|
8
|
+
# For example: {Ryo::Enumerable Ryo::Enumerable}
|
9
|
+
# methods receive 'self' as an argument rather than from the
|
10
|
+
# surrounding context. The methods implemented by this
|
11
|
+
# module are available as singleton methods on the {Ryo Ryo}
|
12
|
+
# module.
|
8
13
|
module Ryo::Enumerable
|
9
14
|
##
|
10
|
-
# The {#each}
|
11
|
-
#
|
15
|
+
# The {#each} method iterates through a Ryo object, and
|
16
|
+
# yields two parameters: a key, and a value
|
12
17
|
#
|
13
18
|
# @example
|
14
19
|
# point_a = Ryo(x: 1, y: 2)
|
@@ -18,23 +23,19 @@ module Ryo::Enumerable
|
|
18
23
|
# # ["y", 2]
|
19
24
|
# # ["x", 1]
|
20
25
|
#
|
21
|
-
# @param
|
22
|
-
# A Ryo object.
|
23
|
-
#
|
24
|
-
# @param ancestors (see #each_ryo)
|
25
|
-
#
|
26
|
+
# @param (see #each_ryo)
|
26
27
|
# @return [<Enumerator, Array>]
|
27
|
-
# Returns an Enumerator when a block is not given, otherwise returns an Array.
|
28
28
|
def each(ryo, ancestors: nil)
|
29
29
|
return enum_for(:each, ryo) unless block_given?
|
30
|
-
each_ryo(ryo, ancestors:
|
30
|
+
each_ryo(ryo, ancestors:) do |_, key, value|
|
31
31
|
yield(key, value)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
##
|
36
|
-
# The {#each_ryo} method iterates through a Ryo object,
|
37
|
-
# {#each_ryo} yields three parameters:
|
36
|
+
# The {#each_ryo} method iterates through a Ryo object,
|
37
|
+
# and its prototypes. {#each_ryo} yields three parameters:
|
38
|
+
# a Ryo object, a key, and a value
|
38
39
|
#
|
39
40
|
# @example
|
40
41
|
# point_a = Ryo(x: 1, y: 2)
|
@@ -45,15 +46,13 @@ module Ryo::Enumerable
|
|
45
46
|
# # [point_a, "y", 2]
|
46
47
|
#
|
47
48
|
# @param [<Ryo::BasicObject, Ryo::Object>] ryo
|
48
|
-
# A Ryo object.
|
49
|
-
#
|
50
49
|
# @param [Integer] ancestors
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
50
|
+
# "ancestors" is an integer that defines the traversal depth
|
51
|
+
# of a {Ryo::Enumerable Ryo::Enumerable} method. 0 covers a
|
52
|
+
# Ryo object, and none of the prototypes in its prototype
|
53
|
+
# chain. 1 covers a Ryo object, and one of the prototypes
|
54
|
+
# in its prototype chain - and so on. The default covers
|
55
|
+
# the entire prototype chain.
|
57
56
|
# @return [<Ryo::BasicObject, Ryo::Object>]
|
58
57
|
def each_ryo(ryo, ancestors: nil)
|
59
58
|
proto_chain = [ryo, *prototype_chain_of(ryo)]
|
@@ -67,17 +66,19 @@ module Ryo::Enumerable
|
|
67
66
|
end
|
68
67
|
|
69
68
|
##
|
70
|
-
# The {#map} method creates a copy of a Ryo object,
|
71
|
-
# on the copy and
|
69
|
+
# The {#map} method creates a copy of a Ryo object,
|
70
|
+
# and then performs a map operation on the copy and
|
71
|
+
# its prototypes
|
72
72
|
#
|
73
|
-
# @param (see #
|
74
|
-
# @return
|
73
|
+
# @param (see #each_ryo)
|
74
|
+
# @return [<Ryo::Object, Ryo::BasicObject>]
|
75
75
|
def map(ryo, ancestors: nil, &b)
|
76
|
-
map!(Ryo.dup(ryo), ancestors
|
76
|
+
map!(Ryo.dup(ryo), ancestors:, &b)
|
77
77
|
end
|
78
78
|
|
79
79
|
##
|
80
|
-
# The {#map!} method performs an in-place map operation
|
80
|
+
# The {#map!} method performs an in-place map operation
|
81
|
+
# on a Ryo object, and its prototypes
|
81
82
|
#
|
82
83
|
# @example
|
83
84
|
# point = Ryo(x: 2, y: 4)
|
@@ -85,31 +86,28 @@ module Ryo::Enumerable
|
|
85
86
|
# [point.x, point.y]
|
86
87
|
# # => [4, 8]
|
87
88
|
#
|
88
|
-
# @param
|
89
|
-
# A Ryo object.
|
90
|
-
#
|
91
|
-
# @param ancestors (see #each_ryo)
|
92
|
-
#
|
89
|
+
# @param (see #each_ryo)
|
93
90
|
# @return [<Ryo::Object, Ryo::BasicObject>]
|
94
91
|
def map!(ryo, ancestors: nil)
|
95
|
-
each_ryo(ryo, ancestors:
|
92
|
+
each_ryo(ryo, ancestors:) do |ryo, key, value|
|
96
93
|
ryo[key] = yield(key, value)
|
97
94
|
end
|
98
95
|
end
|
99
96
|
|
100
97
|
##
|
101
|
-
# The {#select} method creates a copy of a Ryo object, and
|
102
|
-
# on the copy and its
|
98
|
+
# The {#select} method creates a copy of a Ryo object, and
|
99
|
+
# then performs a filter operation on the copy and its
|
100
|
+
# prototypes
|
103
101
|
#
|
104
|
-
# @param (see #
|
105
|
-
# @return
|
102
|
+
# @param (see #each_ryo)
|
103
|
+
# @return [<Ryo::Object, Ryo::BasicObject>]
|
106
104
|
def select(ryo, ancestors: nil, &b)
|
107
|
-
select!(Ryo.dup(ryo), ancestors
|
105
|
+
select!(Ryo.dup(ryo), ancestors:, &b)
|
108
106
|
end
|
109
107
|
|
110
108
|
##
|
111
|
-
# The {#select!} method performs an in-place filter operation
|
112
|
-
# its prototypes
|
109
|
+
# The {#select!} method performs an in-place filter operation
|
110
|
+
# on a Ryo object, and its prototypes
|
113
111
|
#
|
114
112
|
# @example
|
115
113
|
# point_a = Ryo(x: 1, y: 2, z: 3)
|
@@ -118,31 +116,27 @@ module Ryo::Enumerable
|
|
118
116
|
# [point_b.x, point_b.y, point_b.z]
|
119
117
|
# # => [1, 2, nil]
|
120
118
|
#
|
121
|
-
# @param
|
122
|
-
# A Ryo object.
|
123
|
-
#
|
124
|
-
# @param ancestors (see #each_ryo)
|
125
|
-
#
|
119
|
+
# @param (see #each_ryo)
|
126
120
|
# @return [<Ryo::Object, Ryo::BasicObject>]
|
127
121
|
def select!(ryo, ancestors: nil)
|
128
|
-
each_ryo(ryo, ancestors:
|
122
|
+
each_ryo(ryo, ancestors:) do |ryo, key, value|
|
129
123
|
delete(ryo, key) unless yield(key, value)
|
130
124
|
end
|
131
125
|
end
|
132
126
|
|
133
127
|
##
|
134
|
-
# The {#reject} method creates a copy of a Ryo object, and then
|
135
|
-
# on the copy and its prototypes
|
128
|
+
# The {#reject} method creates a copy of a Ryo object, and then
|
129
|
+
# performs a filter operation on the copy and its prototypes
|
136
130
|
#
|
137
|
-
# @param (see #
|
138
|
-
# @return
|
131
|
+
# @param (see #each_ryo)
|
132
|
+
# @return [<Ryo::Object, Ryo::BasicObject>]
|
139
133
|
def reject(ryo, ancestors: nil, &b)
|
140
|
-
reject!(Ryo.dup(ryo), ancestors
|
134
|
+
reject!(Ryo.dup(ryo), ancestors:, &b)
|
141
135
|
end
|
142
136
|
|
143
137
|
##
|
144
|
-
# The {#reject!} method performs an in-place filter operation
|
145
|
-
# its prototypes
|
138
|
+
# The {#reject!} method performs an in-place filter operation
|
139
|
+
# on a Ryo object, and its prototypes
|
146
140
|
#
|
147
141
|
# @example
|
148
142
|
# point_a = Ryo(x: 1, y: 2, z: 3)
|
@@ -151,51 +145,39 @@ module Ryo::Enumerable
|
|
151
145
|
# [point_b.x, point_b.y, point_b.z]
|
152
146
|
# # => [1, 2, nil]
|
153
147
|
#
|
154
|
-
# @param
|
155
|
-
# A Ryo object.
|
156
|
-
#
|
157
|
-
# @param ancestors (see #each_ryo)
|
158
|
-
#
|
148
|
+
# @param (see #each_ryo)
|
159
149
|
# @return [<Ryo::Object, Ryo::BasicObject>]
|
160
150
|
def reject!(ryo, ancestors: nil)
|
161
|
-
each_ryo(ryo, ancestors:
|
151
|
+
each_ryo(ryo, ancestors:) do |ryo, key, value|
|
162
152
|
delete(ryo, key) if yield(key, value)
|
163
153
|
end
|
164
154
|
end
|
165
155
|
|
166
156
|
##
|
167
|
-
#
|
168
|
-
# key / value pair to a block. If the block ever returns a truthy value, {#any?} will
|
169
|
-
# break from the iteration and return true - otherwise false will be returned.
|
170
|
-
#
|
171
|
-
# @param ancestors (see #each_ryo)
|
157
|
+
# @param (see #each_ryo)
|
172
158
|
# @return [Boolean]
|
159
|
+
# Returns true when the given block evaluates to
|
160
|
+
# a truthy value for at least one iteration
|
173
161
|
def any?(ryo, ancestors: nil)
|
174
|
-
each_ryo(ryo, ancestors:
|
162
|
+
each_ryo(ryo, ancestors:) do |_, key, value|
|
175
163
|
return true if yield(key, value)
|
176
164
|
end
|
177
165
|
false
|
178
166
|
end
|
179
167
|
|
180
168
|
##
|
181
|
-
#
|
182
|
-
# key / value pair to a block. If the block ever returns a falsey value, {#all?} will
|
183
|
-
# break from the iteration and return false - otherwise true will be returned.
|
184
|
-
#
|
185
|
-
# @param ancestors (see #each_ryo)
|
169
|
+
# @param (see #each_ryo)
|
186
170
|
# @return [Boolean]
|
171
|
+
# Returns true when the given block evaluates to a
|
172
|
+
# truthy value for every iteration
|
187
173
|
def all?(ryo, ancestors: nil)
|
188
|
-
each_ryo(ryo, ancestors:
|
174
|
+
each_ryo(ryo, ancestors:) do |_, key, value|
|
189
175
|
return false unless yield(key, value)
|
190
176
|
end
|
191
177
|
true
|
192
178
|
end
|
193
179
|
|
194
180
|
##
|
195
|
-
# The {#find} method iterates through a Ryo object, and its prototypes - yielding a
|
196
|
-
# key / value pair to a block. If the block ever returns a truthy value, {#find} will
|
197
|
-
# break from the iteration and return a Ryo object - otherwise nil will be returned.
|
198
|
-
#
|
199
181
|
# @example
|
200
182
|
# point_a = Ryo(x: 5)
|
201
183
|
# point_b = Ryo({y: 10}, point_a)
|
@@ -203,10 +185,11 @@ module Ryo::Enumerable
|
|
203
185
|
# ryo = Ryo.find(point_c) { |key, value| value == 5 }
|
204
186
|
# ryo == point_a # => true
|
205
187
|
#
|
206
|
-
# @param
|
188
|
+
# @param (see #each_ryo)
|
207
189
|
# @return [<Ryo::Object, Ryo::BasicObject>, nil]
|
190
|
+
# Returns a Ryo object, or nil
|
208
191
|
def find(ryo, ancestors: nil)
|
209
|
-
each_ryo(ryo, ancestors:
|
192
|
+
each_ryo(ryo, ancestors:) do |ryo, key, value|
|
210
193
|
return ryo if yield(key, value)
|
211
194
|
end
|
212
195
|
nil
|