ryo.rb 0.4.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.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/specs.yml +23 -0
  3. data/.gitignore +6 -0
  4. data/.gitlab-ci.yml +9 -0
  5. data/.rubocop.yml +56 -0
  6. data/.yardoc-template/default/fulldoc/html/css/0x1eef.css +15 -0
  7. data/.yardoc-template/default/layout/html/setup.rb +5 -0
  8. data/.yardoc-template/default/module/setup.rb +7 -0
  9. data/.yardopts +4 -0
  10. data/Gemfile +5 -0
  11. data/LICENSE.txt +22 -0
  12. data/README.md +373 -0
  13. data/Rakefile +3 -0
  14. data/lib/ryo/basic_object.rb +58 -0
  15. data/lib/ryo/builder.rb +106 -0
  16. data/lib/ryo/enumerable.rb +214 -0
  17. data/lib/ryo/function.rb +68 -0
  18. data/lib/ryo/keywords.rb +67 -0
  19. data/lib/ryo/lazy.rb +4 -0
  20. data/lib/ryo/object.rb +58 -0
  21. data/lib/ryo/reflect.rb +379 -0
  22. data/lib/ryo/version.rb +5 -0
  23. data/lib/ryo.rb +197 -0
  24. data/ryo.rb.gemspec +21 -0
  25. data/share/ryo.rb/examples/1.0_prototypes_point_object.rb +12 -0
  26. data/share/ryo.rb/examples/1.1_prototypes_ryo_fn.rb +14 -0
  27. data/share/ryo.rb/examples/2.0_iteration_each.rb +13 -0
  28. data/share/ryo.rb/examples/2.1_iteration_map.rb +16 -0
  29. data/share/ryo.rb/examples/2.2_iteration_ancestors.rb +13 -0
  30. data/share/ryo.rb/examples/3.0_recursion_ryo_from.rb +13 -0
  31. data/share/ryo.rb/examples/3.1_recursion_ryo_from_with_array.rb +19 -0
  32. data/share/ryo.rb/examples/3.2_recursion_ryo_from_with_openstruct.rb +14 -0
  33. data/share/ryo.rb/examples/4.0_basicobject_ryo_basicobject.rb +12 -0
  34. data/share/ryo.rb/examples/4.1_basicobject_ryo_basicobject_from.rb +13 -0
  35. data/share/ryo.rb/examples/5_collisions_resolution_strategy.rb +8 -0
  36. data/share/ryo.rb/examples/6_beyond_hash_objects.rb +20 -0
  37. data/share/ryo.rb/examples/7_ryo_lazy.rb +14 -0
  38. data/share/ryo.rb/examples/setup.rb +3 -0
  39. data/spec/readme_spec.rb +79 -0
  40. data/spec/ryo_basic_object_spec.rb +60 -0
  41. data/spec/ryo_enumerable_spec.rb +197 -0
  42. data/spec/ryo_keywords_spec.rb +86 -0
  43. data/spec/ryo_object_spec.rb +71 -0
  44. data/spec/ryo_prototypes_spec.rb +45 -0
  45. data/spec/ryo_reflect_spec.rb +175 -0
  46. data/spec/ryo_spec.rb +130 -0
  47. data/spec/setup.rb +5 -0
  48. metadata +173 -0
@@ -0,0 +1,379 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The {Ryo::Reflect Ryo::Reflect} module implements equivalents
5
+ # from JavaScript's [`Relfect` object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect),
6
+ # and equivalents for some of the static methods on JavaScript's
7
+ # [`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) constructor.
8
+ #
9
+ # This module also implements Ryo-specific reflection features as well. The
10
+ # instance methods of this module are available as singleton methods
11
+ # on the {Ryo Ryo} module.
12
+ module Ryo::Reflect
13
+ extend self
14
+
15
+ ##
16
+ # @group JavaScript equivalents (Reflect)
17
+
18
+ ##
19
+ # Equivalent to JavaScript's `Reflect.getPrototypeOf`.
20
+ #
21
+ # @param [Ryo] ryo
22
+ # A Ryo object.
23
+ #
24
+ # @return [Ryo, nil]
25
+ # Returns the prototype of the *ryo* object.
26
+ def prototype_of(ryo)
27
+ kernel(:instance_variable_get)
28
+ .bind_call(ryo, :@_proto)
29
+ end
30
+
31
+ ##
32
+ # Equivalent to JavaScript's `Reflect.setPrototypeOf`.
33
+ #
34
+ # @param [Ryo] ryo
35
+ # A Ryo object.
36
+ #
37
+ # @param [Ryo] prototype
38
+ # The prototype to assign to *ryo*.
39
+ #
40
+ # @return [nil]
41
+ def set_prototype_of(ryo, prototype)
42
+ kernel(:instance_variable_set)
43
+ .bind_call(ryo, :@_proto, prototype)
44
+ nil
45
+ end
46
+
47
+ ##
48
+ # Equivalent to JavaScript's `Reflect.defineProperty`.
49
+ #
50
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
51
+ # A Ryo object.
52
+ #
53
+ # @param [<String, #to_s>] property
54
+ # The name of the property.
55
+ #
56
+ # @param [Object, BasicObject] value
57
+ # The value of the property.
58
+ #
59
+ # @return [void]
60
+ def define_property(ryo, property, value)
61
+ table, property = table_of(ryo), property.to_s
62
+ kernel(:tap).bind_call(value) { _1.bind!(ryo) if function?(_1) }
63
+ table[property] = value
64
+ # Define setter
65
+ if !setter_defined?(ryo, property) && property[-1] != "?"
66
+ define_method!(ryo, "#{property}=") { ryo[property] = _1 }
67
+ end
68
+ # Define getter
69
+ return if getter_defined?(ryo, property)
70
+ define_method!(ryo, property) { |*args, &b|
71
+ (args.empty? && b.nil?) ? ryo[property] :
72
+ super(*args, &b)
73
+ }
74
+ nil
75
+ end
76
+
77
+ ##
78
+ # Equivalent to JavaScript's `Reflect.ownKeys`, and
79
+ # JavaScript's `Object.keys`.
80
+ #
81
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
82
+ # A Ryo object.
83
+ #
84
+ # @return [Array<String>]
85
+ # Returns the properties defined on a Ryo object.
86
+ def properties_of(ryo)
87
+ table_of(ryo).keys
88
+ end
89
+
90
+ # @endgroup
91
+
92
+ ##
93
+ # @group JavaScript equivalents (Object)
94
+
95
+ ##
96
+ # Equivalent to JavaScript's `Object.hasOwn`,
97
+ # and `Object.prototype.hasOwnProperty`.
98
+ #
99
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
100
+ # A Ryo object.
101
+ #
102
+ # @param [<String, #to_s>] property
103
+ # A property name.
104
+ #
105
+ # @return [Boolean]
106
+ # Returns true when **property** is a member of a Ryo object.
107
+ def property?(ryo, property)
108
+ table_of(ryo).key?(property.to_s)
109
+ end
110
+
111
+ ##
112
+ # Equivalent to JavaScript's `Object.assign`.
113
+ #
114
+ #
115
+ # @param [Ryo, Hash, #to_hash] target
116
+ # The target object.
117
+ #
118
+ # @param [Ryo, Hash, #to_hash] sources
119
+ # A variable number of source objects that
120
+ # will be merged into the target object.
121
+ #
122
+ # @return [Ryo]
123
+ # Returns the modified target object.
124
+ def assign(target, *sources)
125
+ sources.each do |source|
126
+ to_hash(source).each { target[_1.to_s] = _2 }
127
+ end
128
+ target
129
+ end
130
+ # @endgroup
131
+
132
+ ##
133
+ # @group Ryo-specific
134
+
135
+ ##
136
+ # The {#delete!} method deletes a property from a Ryo object,
137
+ # and from the prototypes in its prototype chain.
138
+ #
139
+ # @see Ryo::Keywords#delete
140
+ #
141
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
142
+ # A Ryo object.
143
+ #
144
+ # @param [<String, #to_s>] property
145
+ # A property name.
146
+ #
147
+ # @return [void]
148
+ def delete!(ryo, property)
149
+ [ryo, *prototype_chain_of(ryo)].each do
150
+ Ryo.delete(_1, property.to_s)
151
+ end
152
+ end
153
+
154
+ ##
155
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
156
+ # A Ryo object.
157
+ #
158
+ # @return [Array<Ryo::Object, Ryo::BasicObject>]
159
+ # Returns the prototype chain of a Ryo object.
160
+ def prototype_chain_of(ryo)
161
+ prototypes = []
162
+ loop do
163
+ ryo = prototype_of(ryo)
164
+ break unless ryo
165
+ prototypes.push(ryo)
166
+ end
167
+ prototypes
168
+ end
169
+
170
+ ##
171
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
172
+ # A Ryo object.
173
+ #
174
+ # @param [Boolean] recursive
175
+ # When true, nested Ryo objects are replaced by
176
+ # their table as well.
177
+ #
178
+ # @return [Hash]
179
+ # Returns the table of a Ryo object.
180
+ def table_of(ryo, recursive: false)
181
+ table = kernel(:instance_variable_get).bind_call(ryo, :@_table)
182
+ if recursive
183
+ table.each do |key, value|
184
+ if ryo?(value)
185
+ table[key] = table_of(value, recursive:)
186
+ end
187
+ end
188
+ end
189
+ table
190
+ end
191
+
192
+ ##
193
+ # Sets the table of a Ryo object.
194
+ #
195
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
196
+ # A Ryo object.
197
+ #
198
+ # @param [Hash] table
199
+ # The table to assign to a Ryo object.
200
+ #
201
+ # @return [nil]
202
+ def set_table_of(ryo, table)
203
+ kernel(:instance_variable_set)
204
+ .bind_call(ryo, :@_table, table)
205
+ nil
206
+ end
207
+
208
+ ##
209
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
210
+ # A Ryo object.
211
+ #
212
+ # @param [<String, Symbol>] method
213
+ # The name of a method.
214
+ #
215
+ # @param [::Object, ::BasicObject] args
216
+ # Zero or more arguments to call **method** with.
217
+ #
218
+ # @param [Proc] b
219
+ # An optional block to pass to **method**.
220
+ #
221
+ # @return [::Object, ::BasicObject]
222
+ # Returns the return value of the method call.
223
+ def call_method(ryo, method, *args, &b)
224
+ kernel(:__send__)
225
+ .bind_call(ryo, method, *args, &b)
226
+ end
227
+
228
+ ##
229
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
230
+ # A Ryo object.
231
+ #
232
+ # @return [Class]
233
+ # Returns the class of a Ryo object.
234
+ def class_of(ryo)
235
+ kernel(:class).bind_call(ryo)
236
+ end
237
+
238
+ ##
239
+ # @param [Ryo::Function, Object, BasicObject] obj
240
+ # An object.
241
+ #
242
+ # @return [Boolean]
243
+ # Returns true when the given object is a Ryo function.
244
+ def function?(obj)
245
+ Ryo::Function === obj
246
+ end
247
+
248
+ ##
249
+ # @param [Ryo::Function, Object, BasicObject] obj
250
+ # An object.
251
+ #
252
+ # @return [Boolean]
253
+ # Returns true when the given object is an instance
254
+ # of {Ryo::Lazy Ryo::Lazy}.
255
+ def lazy?(obj)
256
+ Ryo::Lazy === obj
257
+ end
258
+
259
+ ##
260
+ # @example
261
+ # Ryo.ryo?(Ryo::Object(x: 5, y: 12)) # => true
262
+ # Ryo.ryo?(Ryo::BasicObject(x: 10, y: 20)) # => true
263
+ # Ryo.ryo?(Object.new) # => false
264
+ #
265
+ # @param [Object, BasicObject] obj
266
+ # An object.
267
+ #
268
+ # @return [Boolean]
269
+ # Returns true when the given object is a Ryo object.
270
+ def ryo?(obj)
271
+ Ryo === obj
272
+ end
273
+
274
+ ##
275
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo1
276
+ # A Ryo object.
277
+ #
278
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo2
279
+ # A Ryo object.
280
+ #
281
+ # @return [Boolean]
282
+ # Returns true when two Ryo objects are the same object.
283
+ def equal?(ryo1, ryo2)
284
+ kernel(:equal?).bind_call(ryo1, ryo2)
285
+ end
286
+
287
+ ##
288
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
289
+ # A Ryo object.
290
+ #
291
+ # @return [String]
292
+ # Returns a String representation of a Ryo object.
293
+ def inspect_object(ryo)
294
+ format(
295
+ "#<Ryo object=%{object} proto=%{proto} table=%{table}>",
296
+ object: Object.instance_method(:to_s).bind_call(ryo),
297
+ proto: prototype_of(ryo).inspect,
298
+ table: table_of(ryo).inspect
299
+ )
300
+ end
301
+ # @endgroup
302
+
303
+ ##
304
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
305
+ # A Ryo object.
306
+ #
307
+ # @param [<String, Symbol>] method
308
+ # The name of the method.
309
+ #
310
+ # @param [Proc] b
311
+ # The method's body.
312
+ #
313
+ # @private
314
+ private def define_method!(ryo, method, &b)
315
+ kernel(:define_singleton_method)
316
+ .bind_call(ryo, method, &b)
317
+ end
318
+
319
+ ##
320
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
321
+ # A Ryo object.
322
+ #
323
+ # @param [<String, #to_s>] property
324
+ # The name of the property.
325
+ #
326
+ # @return [Boolean]
327
+ # Returns true when the property has been
328
+ # defined with a getter method.
329
+ #
330
+ # @private
331
+ private def getter_defined?(ryo, property)
332
+ kernel(:method)
333
+ .bind_call(ryo, property)
334
+ .source_location
335
+ &.dig(0) == __FILE__
336
+ end
337
+
338
+ ##
339
+ #
340
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
341
+ # A Ryo object.
342
+ #
343
+ # @param [<String, #to_s>] property
344
+ # The name of the property.
345
+ #
346
+ # @return [Boolean]
347
+ # Returns true when the property has been
348
+ # defined with a setter method.
349
+ #
350
+ # @private
351
+ private def setter_defined?(ryo, property)
352
+ getter_defined?(ryo, "#{property}=")
353
+ end
354
+
355
+ ##
356
+ # @private
357
+ private def merge!(obj1, obj2)
358
+ obj1, obj2 = to_hash(obj1), to_hash(obj2)
359
+ obj2.each { obj1[_1.to_s] = _2 }
360
+ obj1
361
+ end
362
+
363
+ ##
364
+ # @private
365
+ private def to_hash(obj)
366
+ if ryo?(obj)
367
+ table_of(obj)
368
+ else
369
+ Hash.try_convert(obj)
370
+ end
371
+ end
372
+
373
+ ##
374
+ # @private
375
+ def kernel(name)
376
+ Module.instance_method(name)
377
+ end
378
+ # @endgroup
379
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ryo
4
+ VERSION = "0.4.4"
5
+ end
data/lib/ryo.rb ADDED
@@ -0,0 +1,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # The {Ryo Ryo} module implements most of its behavior as singleton methods
5
+ # that are inherited from the {Ryo::Reflect Ryo::Reflect}, and
6
+ # {Ryo::Keywords Ryo:Keywords} modules.
7
+ #
8
+ # @example
9
+ # # Ryo.delete
10
+ # point = Ryo(x: 0, y: 0)
11
+ # Ryo.delete(point, "x")
12
+ # point.x # => nil
13
+ #
14
+ # # Ryo.assign
15
+ # point = Ryo.assign(Ryo({}), {x: 0}, {y: 0})
16
+ # point.x # => 0
17
+ module Ryo
18
+ require_relative "ryo/reflect"
19
+ require_relative "ryo/keywords"
20
+ require_relative "ryo/builder"
21
+ require_relative "ryo/basic_object"
22
+ require_relative "ryo/object"
23
+ require_relative "ryo/function"
24
+ require_relative "ryo/lazy"
25
+ require_relative "ryo/enumerable"
26
+
27
+ extend Ryo::Reflect
28
+ extend Ryo::Keywords
29
+ extend Ryo::Enumerable
30
+
31
+ ##
32
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
33
+ # A Ryo object.
34
+ #
35
+ # @param [Module] mod
36
+ # A module to extend a Ryo object with.
37
+ #
38
+ # @return [<Ryo::Object, Ryo::BasicObject>]
39
+ # Returns a Ryo object extended by **mod**.
40
+ def self.extend!(ryo, mod)
41
+ kernel(:extend).bind_call(ryo, mod)
42
+ end
43
+
44
+ ##
45
+ # Duplicates a Ryo object, and its prototype(s).
46
+ #
47
+ # @param [<Ryo::Object, Ryo::BasicObject>] ryo
48
+ # A Ryo object.
49
+ #
50
+ # @return [<Ryo::Object, Ryo::BasicObject>]
51
+ # Returns a duplicated Ryo object.
52
+ def self.dup(ryo)
53
+ duplicate = extend!(
54
+ kernel(:dup).bind_call(ryo),
55
+ self
56
+ )
57
+ if proto = prototype_of(duplicate)
58
+ set_prototype_of(duplicate, dup(proto))
59
+ end
60
+ duplicate
61
+ end
62
+
63
+ ##
64
+ # Creates a lazy Ryo value.
65
+ #
66
+ # @param [Proc] b
67
+ # A proc that is evaluated when a property is first accessed.
68
+ #
69
+ # @return [Ryo::Lazy]
70
+ # Returns an instance of {Ryo::Lazy Ryo::Lazy}.
71
+ def self.lazy(&b)
72
+ Ryo::Lazy.new(&b)
73
+ end
74
+
75
+ ##
76
+ # Creates a Ryo object by recursively walking a Hash object.
77
+ #
78
+ # @param props (see Ryo::Builder.build)
79
+ # @param prototype (see Ryo::Builder.build)
80
+ #
81
+ # @return [Ryo::Object]
82
+ # Returns an instance of {Ryo::Object Ryo::Object}.
83
+ def self.from(props, prototype = nil)
84
+ Ryo::Object.from(props, prototype)
85
+ end
86
+
87
+ ##
88
+ # Returns the prototype of self, or "nil" if self has no prototype.
89
+ #
90
+ # @return [<Ryo::Object, Ryo::BasicObject>, nil]
91
+ def __proto__
92
+ @_proto
93
+ end
94
+
95
+ ##
96
+ # @param [String] property
97
+ # A property name.
98
+ #
99
+ # @return [<Object, BasicObject>, nil]
100
+ # Returns the value at **property**, or nil.
101
+ #
102
+ # @note
103
+ # This method will first try to read **property** from self, and if
104
+ # it is not found on self the chain of prototypes will be traversed
105
+ # through instead.
106
+ def [](property)
107
+ property = property.to_s
108
+ if Ryo.property?(self, property)
109
+ v = @_table[property]
110
+ Ryo.lazy?(v) ? self[property] = v.call : v
111
+ else
112
+ return unless @_proto
113
+ Ryo.call_method(@_proto, property)
114
+ end
115
+ end
116
+
117
+ ##
118
+ # Assigns a property to self.
119
+ #
120
+ # @param [String] property
121
+ # A property name.
122
+ #
123
+ # @param [<Object,BasicObject>] value
124
+ # The value.
125
+ #
126
+ # @return [void]
127
+ def []=(property, value)
128
+ Ryo.define_property(self, property.to_s, value)
129
+ end
130
+
131
+ ##
132
+ # @param [<Ryo::Object, Ryo::BasicObject>, Hash, #to_h] other
133
+ # An object to compare against.
134
+ #
135
+ # @return [Boolean]
136
+ # Returns true **other** is equal to self.
137
+ def ==(other)
138
+ if Ryo.ryo?(other)
139
+ @_table == Ryo.table_of(other)
140
+ else
141
+ other = Hash.try_convert(other)
142
+ return false unless other
143
+ @_table == other.map { [_1.to_s, _2] }.to_h
144
+ end
145
+ end
146
+ alias_method :eql?, :==
147
+
148
+ ##
149
+ # @return [String]
150
+ # Returns a String representation of a Ryo object.
151
+ def inspect
152
+ Ryo.inspect_object(self)
153
+ end
154
+
155
+ ##
156
+ # @private
157
+ def pretty_print(q)
158
+ q.text(inspect)
159
+ end
160
+
161
+ ##
162
+ # @private
163
+ def respond_to?(property, include_all = false)
164
+ respond_to_missing?(property, include_all)
165
+ end
166
+
167
+ ##
168
+ # @private
169
+ def respond_to_missing?(property, include_all = false)
170
+ true
171
+ end
172
+
173
+ ##
174
+ # @private
175
+ def method_missing(name, *args, &b)
176
+ property = name.to_s
177
+ if property[-1] == "="
178
+ property = property[0..-2]
179
+ self[property] = args.first
180
+ elsif Ryo.property?(self, property)
181
+ self[property]
182
+ elsif @_proto
183
+ Ryo.call_method(@_proto, name, *args, &b)
184
+ .tap { _1.bind!(self) if Ryo.function?(_1) }
185
+ end
186
+ end
187
+ end
188
+
189
+ ##
190
+ # @param props (see Ryo::Builder.build)
191
+ # @param prototype (see Ryo::Builder.build)
192
+ #
193
+ # @return [Ryo::Object]
194
+ # Returns a Ryo object.
195
+ def Ryo(props, prototype = nil)
196
+ Ryo::Object.create(props, prototype)
197
+ end
data/ryo.rb.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "./lib/ryo/version"
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "ryo.rb"
6
+ gem.authors = ["0x1eef"]
7
+ gem.email = ["0x1eef@protonmail.com"]
8
+ gem.homepage = "https://github.com/0x1eef/ryo.rb#readme"
9
+ gem.version = Ryo::VERSION
10
+ gem.licenses = ["MIT"]
11
+ gem.files = `git ls-files`.split($/)
12
+ gem.require_paths = ["lib"]
13
+ gem.description = "Ryo implements prototype-based inheritance, in Ruby."
14
+ gem.summary = gem.description
15
+ gem.add_development_dependency "yard", "~> 0.9"
16
+ gem.add_development_dependency "redcarpet", "~> 3.5"
17
+ gem.add_development_dependency "rspec", "~> 3.10"
18
+ gem.add_development_dependency "rubocop-rspec", "~> 2.12"
19
+ gem.add_development_dependency "standard", "~> 1.9"
20
+ gem.add_development_dependency "test-cmd.rb", "~> 0.4"
21
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "setup"
4
+ require "ryo"
5
+
6
+ point_x = Ryo(x: 5)
7
+ point_y = Ryo({y: 10}, point_x)
8
+ point = Ryo({}, point_y)
9
+ p [point.x, point.y]
10
+
11
+ ##
12
+ # [5, 10]
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "setup"
4
+ require "ryo"
5
+
6
+ point_x = Ryo(x: 5)
7
+ point_y = Ryo({y: 10}, point_x)
8
+ point = Ryo({
9
+ multiply: Ryo.fn { |m| [x * m, y * m] }
10
+ }, point_y)
11
+ p point.multiply.call(2)
12
+
13
+ ##
14
+ # [10, 20]
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "setup"
4
+ require "ryo"
5
+
6
+ point = Ryo(x: 10, y: 20)
7
+ Ryo.each(point) do |key, value|
8
+ p [key, value]
9
+ end
10
+
11
+ ##
12
+ # ["x", 10]
13
+ # ["y", 20]
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "setup"
4
+ require "ryo"
5
+
6
+ point_x = Ryo(x: 2)
7
+ point_y = Ryo({y: 4}, point_x)
8
+ point = Ryo({}, point_y)
9
+
10
+ Ryo.map!(point) { |key, value| value * 2 }
11
+ p [point.x, point.y]
12
+ p [point_x.x, point_y.y]
13
+
14
+ ##
15
+ # [4, 8]
16
+ # [4, 8]
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "setup"
4
+ require "ryo"
5
+
6
+ point_x = Ryo(x: 5)
7
+ point_y = Ryo({y: 10}, point_x)
8
+ point = Ryo({}, point_y)
9
+
10
+ p Ryo.find(point, ancestors: 0) { |k,v| v == 5 } # => nil
11
+ p Ryo.find(point, ancestors: 1) { |k,v| v == 5 } # => nil
12
+ p Ryo.find(point, ancestors: 2) { |k,v| v == 5 }.x # => point_x.x
13
+ p Ryo.find(point) { |k,v| v == 5 }.x # => point_x.x
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "setup"
4
+ require "ryo"
5
+
6
+ point = Ryo.from({
7
+ x: {to_i: 0},
8
+ y: {to_i: 10}
9
+ })
10
+ p [point.x.to_i, point.y.to_i]
11
+
12
+ ##
13
+ # [0, 10]
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "setup"
4
+ require "ryo"
5
+
6
+ points = Ryo.from([
7
+ {x: {to_i: 2}},
8
+ "foobar",
9
+ {y: {to_i: 4}}
10
+ ])
11
+
12
+ p points[0].x.to_i
13
+ p points[1]
14
+ p points[2].y.to_i
15
+
16
+ ##
17
+ # 2
18
+ # "foobar"
19
+ # 4