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.
- checksums.yaml +7 -0
- data/.github/workflows/specs.yml +23 -0
- data/.gitignore +6 -0
- data/.gitlab-ci.yml +9 -0
- data/.rubocop.yml +56 -0
- data/.yardoc-template/default/fulldoc/html/css/0x1eef.css +15 -0
- data/.yardoc-template/default/layout/html/setup.rb +5 -0
- data/.yardoc-template/default/module/setup.rb +7 -0
- data/.yardopts +4 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +373 -0
- data/Rakefile +3 -0
- data/lib/ryo/basic_object.rb +58 -0
- data/lib/ryo/builder.rb +106 -0
- data/lib/ryo/enumerable.rb +214 -0
- data/lib/ryo/function.rb +68 -0
- data/lib/ryo/keywords.rb +67 -0
- data/lib/ryo/lazy.rb +4 -0
- data/lib/ryo/object.rb +58 -0
- data/lib/ryo/reflect.rb +379 -0
- data/lib/ryo/version.rb +5 -0
- data/lib/ryo.rb +197 -0
- data/ryo.rb.gemspec +21 -0
- data/share/ryo.rb/examples/1.0_prototypes_point_object.rb +12 -0
- data/share/ryo.rb/examples/1.1_prototypes_ryo_fn.rb +14 -0
- data/share/ryo.rb/examples/2.0_iteration_each.rb +13 -0
- data/share/ryo.rb/examples/2.1_iteration_map.rb +16 -0
- data/share/ryo.rb/examples/2.2_iteration_ancestors.rb +13 -0
- data/share/ryo.rb/examples/3.0_recursion_ryo_from.rb +13 -0
- data/share/ryo.rb/examples/3.1_recursion_ryo_from_with_array.rb +19 -0
- data/share/ryo.rb/examples/3.2_recursion_ryo_from_with_openstruct.rb +14 -0
- data/share/ryo.rb/examples/4.0_basicobject_ryo_basicobject.rb +12 -0
- data/share/ryo.rb/examples/4.1_basicobject_ryo_basicobject_from.rb +13 -0
- data/share/ryo.rb/examples/5_collisions_resolution_strategy.rb +8 -0
- data/share/ryo.rb/examples/6_beyond_hash_objects.rb +20 -0
- data/share/ryo.rb/examples/7_ryo_lazy.rb +14 -0
- data/share/ryo.rb/examples/setup.rb +3 -0
- data/spec/readme_spec.rb +79 -0
- data/spec/ryo_basic_object_spec.rb +60 -0
- data/spec/ryo_enumerable_spec.rb +197 -0
- data/spec/ryo_keywords_spec.rb +86 -0
- data/spec/ryo_object_spec.rb +71 -0
- data/spec/ryo_prototypes_spec.rb +45 -0
- data/spec/ryo_reflect_spec.rb +175 -0
- data/spec/ryo_spec.rb +130 -0
- data/spec/setup.rb +5 -0
- metadata +173 -0
data/lib/ryo/builder.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# {Ryo::Builder Ryo::Builder} is a module that's used underneath Ryo's public
|
5
|
+
# interface when creating instances of {Ryo::Object Ryo::Object}, and
|
6
|
+
# {Ryo::BasicObject Ryo::BasicObject}. This module is not intended to be
|
7
|
+
# used directly.
|
8
|
+
#
|
9
|
+
# @api private
|
10
|
+
module Ryo::Builder
|
11
|
+
##
|
12
|
+
# @param [<Ryo::Object, Ryo::BasicObject>] buildee
|
13
|
+
# The class of the object to build.
|
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
|
+
#
|
18
|
+
# @param [<Ryo::Object, Ryo::BasicObject>, nil] prototype
|
19
|
+
# The prototype, or nil for none.
|
20
|
+
#
|
21
|
+
# @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.
|
27
|
+
def self.build(buildee, props, prototype = nil)
|
28
|
+
if Ryo.ryo?(props)
|
29
|
+
build(builedee, Ryo.table_of(props), prototype || Ryo.prototype_of(props))
|
30
|
+
else
|
31
|
+
ryo = buildee.new
|
32
|
+
Ryo.set_prototype_of(ryo, prototype)
|
33
|
+
Ryo.set_table_of(ryo, {})
|
34
|
+
Ryo.extend!(ryo, Ryo)
|
35
|
+
props.each_pair { ryo[_1] = _2 }
|
36
|
+
ryo
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Creates a Ryo object by recursively walking a Hash object, or an Array of Hash objects.
|
42
|
+
#
|
43
|
+
# @example
|
44
|
+
# objects = Ryo.from([{x: 0, y: 0}, "foo", {point: {x: 0, y: 0}}])
|
45
|
+
# objects[0].x # => 0
|
46
|
+
# objects[1] # => "foo"
|
47
|
+
# objects[2].point.x # => 0
|
48
|
+
#
|
49
|
+
# @param buildee (see Ryo::Builder.build)
|
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
|
+
#
|
56
|
+
# @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
|
+
def self.recursive_build(buildee, props, prototype = nil)
|
62
|
+
if Ryo.ryo?(props)
|
63
|
+
recursive_build(buildee, Ryo.table_of(props), prototype || Ryo.prototype_of(props))
|
64
|
+
elsif eachless?(props)
|
65
|
+
raise TypeError, "The provided object does not implement #each / #each_pair"
|
66
|
+
elsif !props.respond_to?(:each_pair)
|
67
|
+
map(props) do
|
68
|
+
noop = Ryo.ryo?(_1) || !_1.respond_to?(:each_pair)
|
69
|
+
noop ? _1 : recursive_build(buildee, _1)
|
70
|
+
end
|
71
|
+
else
|
72
|
+
visited = {}
|
73
|
+
props.each_pair { visited[_1] = map_value(buildee, _2) }
|
74
|
+
build(buildee, visited, prototype)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
##
|
79
|
+
# @private
|
80
|
+
def self.map_value(buildee, value)
|
81
|
+
if Ryo.ryo?(value) || eachless?(value)
|
82
|
+
value
|
83
|
+
elsif value.respond_to?(:each_pair)
|
84
|
+
recursive_build(buildee, value)
|
85
|
+
elsif value.respond_to?(:each)
|
86
|
+
map(value) { map_value(buildee, _1) }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
private_class_method :map_value
|
90
|
+
|
91
|
+
##
|
92
|
+
# @private
|
93
|
+
def self.eachless?(value)
|
94
|
+
!value.respond_to?(:each) && !value.respond_to?(:each_pair)
|
95
|
+
end
|
96
|
+
private_class_method :eachless?
|
97
|
+
|
98
|
+
##
|
99
|
+
# @private
|
100
|
+
def self.map(obj)
|
101
|
+
ary = []
|
102
|
+
obj.each { ary.push(yield(_1)) }
|
103
|
+
ary
|
104
|
+
end
|
105
|
+
private_class_method :map
|
106
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# The {Ryo::Enumerable Ryo::Enumerable} module implements methods
|
5
|
+
# for iterating through and performing operations on Ryo objects.
|
6
|
+
# The methods implemented by this module are available as singleton
|
7
|
+
# methods on the {Ryo} module.
|
8
|
+
module Ryo::Enumerable
|
9
|
+
##
|
10
|
+
# The {#each} methods iterates a Ryo object, and yields a key / value pair.
|
11
|
+
# When a block is not given, {#each} returns an Enumerator.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# point_a = Ryo(x: 1, y: 2)
|
15
|
+
# point_b = Ryo(y: 1)
|
16
|
+
# Ryo.each(point_b) { p [_1, _2] }
|
17
|
+
# # ["y", 1]
|
18
|
+
# # ["y", 2]
|
19
|
+
# # ["x", 1]
|
20
|
+
#
|
21
|
+
# @param [Ryo::Object, Ryo::BasicObject] ryo
|
22
|
+
# A Ryo object.
|
23
|
+
#
|
24
|
+
# @param ancestors (see #each_ryo)
|
25
|
+
#
|
26
|
+
# @return [<Enumerator, Array>]
|
27
|
+
# Returns an Enumerator when a block is not given, otherwise returns an Array.
|
28
|
+
def each(ryo, ancestors: nil)
|
29
|
+
return enum_for(:each, ryo) unless block_given?
|
30
|
+
each_ryo(ryo, ancestors: ancestors) do |_, key, value|
|
31
|
+
yield(key, value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# The {#each_ryo} method iterates through a Ryo object, and its prototypes.
|
37
|
+
# {#each_ryo} yields three parameters: a Ryo object, a key, and a value.
|
38
|
+
#
|
39
|
+
# @example
|
40
|
+
# point_a = Ryo(x: 1, y: 2)
|
41
|
+
# point_b = Ryo({y: 3}, point_a)
|
42
|
+
# Ryo.each_ryo(point_b) { |ryo, key, value| p [ryo, key, value] }
|
43
|
+
# # [point_b, "y", 3]
|
44
|
+
# # [point_a, "x", 1]
|
45
|
+
# # [point_a, "y", 2]
|
46
|
+
#
|
47
|
+
# @param [<Ryo::BasicObject, Ryo::Object>] ryo
|
48
|
+
# A Ryo object.
|
49
|
+
#
|
50
|
+
# @param [Integer] ancestors
|
51
|
+
# `ancestors` is an integer that determines how far up the prototype chain a
|
52
|
+
# {Ryo::Enumerable Ryo::Enumerable} method can go. 0 covers a Ryo object,
|
53
|
+
# and none of the prototypes in its prototype chain. 1 covers a Ryo object,
|
54
|
+
# and one of the prototypes in its prototype chain - and so on. The default
|
55
|
+
# behavior is to traverse the entire prototype chain.
|
56
|
+
#
|
57
|
+
# @return [<Ryo::BasicObject, Ryo::Object>]
|
58
|
+
def each_ryo(ryo, ancestors: nil)
|
59
|
+
proto_chain = [ryo, *prototype_chain_of(ryo)]
|
60
|
+
ancestors ||= -1
|
61
|
+
proto_chain[0..ancestors].each do |ryo|
|
62
|
+
properties_of(ryo).each do |key|
|
63
|
+
yield(ryo, key, ryo[key])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
ryo
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# The {#map} method creates a copy of a Ryo object, and then performs a map operation
|
71
|
+
# on the copy and its prototypes.
|
72
|
+
#
|
73
|
+
# @param (see #map!)
|
74
|
+
# @return (see #map!)
|
75
|
+
def map(ryo, ancestors: nil, &b)
|
76
|
+
map!(Ryo.dup(ryo), ancestors: ancestors, &b)
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# The {#map!} method performs an in-place map operation on a Ryo object, and its prototypes.
|
81
|
+
#
|
82
|
+
# @example
|
83
|
+
# point = Ryo(x: 2, y: 4)
|
84
|
+
# Ryo.map!(point) { _2 * 2 }
|
85
|
+
# [point.x, point.y]
|
86
|
+
# # => [4, 8]
|
87
|
+
#
|
88
|
+
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
89
|
+
# A Ryo object.
|
90
|
+
#
|
91
|
+
# @param ancestors (see #each_ryo)
|
92
|
+
#
|
93
|
+
# @return [<Ryo::Object, Ryo::BasicObject>]
|
94
|
+
def map!(ryo, ancestors: nil)
|
95
|
+
each_ryo(ryo, ancestors: ancestors) do |ryo, key, value|
|
96
|
+
ryo[key] = yield(key, value)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# The {#select} method creates a copy of a Ryo object, and then performs a filter operation
|
102
|
+
# on the copy and its prototypes.
|
103
|
+
#
|
104
|
+
# @param (see #select!)
|
105
|
+
# @return (see #select!)
|
106
|
+
def select(ryo, ancestors: nil, &b)
|
107
|
+
select!(Ryo.dup(ryo), ancestors: ancestors, &b)
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# The {#select!} method performs an in-place filter operation on a Ryo object, and
|
112
|
+
# its prototypes.
|
113
|
+
#
|
114
|
+
# @example
|
115
|
+
# point_a = Ryo(x: 1, y: 2, z: 3)
|
116
|
+
# point_b = Ryo({z: 4}, point_a)
|
117
|
+
# Ryo.select!(point_b) { |key, value| %w(x y).include?(key) }
|
118
|
+
# [point_b.x, point_b.y, point_b.z]
|
119
|
+
# # => [1, 2, nil]
|
120
|
+
#
|
121
|
+
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
122
|
+
# A Ryo object.
|
123
|
+
#
|
124
|
+
# @param ancestors (see #each_ryo)
|
125
|
+
#
|
126
|
+
# @return [<Ryo::Object, Ryo::BasicObject>]
|
127
|
+
def select!(ryo, ancestors: nil)
|
128
|
+
each_ryo(ryo, ancestors: ancestors) do |ryo, key, value|
|
129
|
+
delete(ryo, key) unless yield(key, value)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
##
|
134
|
+
# The {#reject} method creates a copy of a Ryo object, and then performs a filter operation
|
135
|
+
# on the copy and its prototypes.
|
136
|
+
#
|
137
|
+
# @param (see #reject!)
|
138
|
+
# @return (see #reject!)
|
139
|
+
def reject(ryo, ancestors: nil, &b)
|
140
|
+
reject!(Ryo.dup(ryo), ancestors: ancestors, &b)
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# The {#reject!} method performs an in-place filter operation on a Ryo object, and
|
145
|
+
# its prototypes.
|
146
|
+
#
|
147
|
+
# @example
|
148
|
+
# point_a = Ryo(x: 1, y: 2, z: 3)
|
149
|
+
# point_b = Ryo({z: 4}, point_a)
|
150
|
+
# Ryo.reject!(point_b) { |key, value| value > 2 }
|
151
|
+
# [point_b.x, point_b.y, point_b.z]
|
152
|
+
# # => [1, 2, nil]
|
153
|
+
#
|
154
|
+
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
155
|
+
# A Ryo object.
|
156
|
+
#
|
157
|
+
# @param ancestors (see #each_ryo)
|
158
|
+
#
|
159
|
+
# @return [<Ryo::Object, Ryo::BasicObject>]
|
160
|
+
def reject!(ryo, ancestors: nil)
|
161
|
+
each_ryo(ryo, ancestors: ancestors) do |ryo, key, value|
|
162
|
+
delete(ryo, key) if yield(key, value)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
##
|
167
|
+
# The {#any?} method iterates through a Ryo object, and its prototypes - yielding a
|
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)
|
172
|
+
# @return [Boolean]
|
173
|
+
def any?(ryo, ancestors: nil)
|
174
|
+
each_ryo(ryo, ancestors: ancestors) do |_, key, value|
|
175
|
+
return true if yield(key, value)
|
176
|
+
end
|
177
|
+
false
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# The {#all?} method iterates through a Ryo object, and its prototypes - yielding a
|
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)
|
186
|
+
# @return [Boolean]
|
187
|
+
def all?(ryo, ancestors: nil)
|
188
|
+
each_ryo(ryo, ancestors: ancestors) do |_, key, value|
|
189
|
+
return false unless yield(key, value)
|
190
|
+
end
|
191
|
+
true
|
192
|
+
end
|
193
|
+
|
194
|
+
##
|
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
|
+
# @example
|
200
|
+
# point_a = Ryo(x: 5)
|
201
|
+
# point_b = Ryo({y: 10}, point_a)
|
202
|
+
# point_c = Ryo({z: 15}, point_b)
|
203
|
+
# ryo = Ryo.find(point_c) { |key, value| value == 5 }
|
204
|
+
# ryo == point_a # => true
|
205
|
+
#
|
206
|
+
# @param ancestors (see #each_ryo)
|
207
|
+
# @return [<Ryo::Object, Ryo::BasicObject>, nil]
|
208
|
+
def find(ryo, ancestors: nil)
|
209
|
+
each_ryo(ryo, ancestors: ancestors) do |ryo, key, value|
|
210
|
+
return ryo if yield(key, value)
|
211
|
+
end
|
212
|
+
nil
|
213
|
+
end
|
214
|
+
end
|
data/lib/ryo/function.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# The {Ryo::Function Ryo::Function} class represents a Ryo
|
5
|
+
# function. The class is usually not used directly but through
|
6
|
+
# {Ryo::Keywords#fn Ryo.fn}. A Ryo function has a special relationship
|
7
|
+
# with Ryo objects: when a Ryo function is assigned as a property
|
8
|
+
# on a Ryo object - the "self" of the function becomes bound to the
|
9
|
+
# Ryo object.
|
10
|
+
class Ryo::Function
|
11
|
+
##
|
12
|
+
# @param [Proc] body
|
13
|
+
# The body of the function as a block.
|
14
|
+
#
|
15
|
+
# @return [Ryo::Function]
|
16
|
+
# Returns an instance of {Ryo::Function Ryo::Function}.
|
17
|
+
def initialize(&body)
|
18
|
+
@body = body
|
19
|
+
@ryo = nil
|
20
|
+
@to_proc = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# @return [<Ryo::Object, Ryo::BasicObject>]
|
25
|
+
# Returns the object that the function's "self" is bound to.
|
26
|
+
def receiver
|
27
|
+
@ryo
|
28
|
+
end
|
29
|
+
alias_method :self, :receiver
|
30
|
+
|
31
|
+
##
|
32
|
+
# Change the receiver (self) of the function.
|
33
|
+
#
|
34
|
+
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
35
|
+
# A Ryo object.
|
36
|
+
#
|
37
|
+
# @return [nil]
|
38
|
+
def bind!(ryo)
|
39
|
+
@ryo = ryo
|
40
|
+
@to_proc = nil
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Call the function.
|
45
|
+
def call(...)
|
46
|
+
to_proc.call(...)
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# @return [Proc]
|
51
|
+
# Returns the function as a lambda bound to {#receiver}.
|
52
|
+
def to_proc
|
53
|
+
@to_proc ||= lambda!(@body)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def lambda!(body)
|
59
|
+
ryo, lambda = @ryo, nil
|
60
|
+
Module.new do
|
61
|
+
define_method(:__function__, &body)
|
62
|
+
lambda = instance_method(:__function__)
|
63
|
+
.bind(ryo)
|
64
|
+
.to_proc
|
65
|
+
end
|
66
|
+
lambda
|
67
|
+
end
|
68
|
+
end
|
data/lib/ryo/keywords.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# The {Ryo::Keywords Ryo::Keywords} module implements Ryo equivalents
|
5
|
+
# to some of JavaScript's keywords - for example: the **in** and **delete**
|
6
|
+
# operators. The instance methods of this module are available as singleton
|
7
|
+
# methods on the {Ryo} module.
|
8
|
+
module Ryo::Keywords
|
9
|
+
##
|
10
|
+
# @example
|
11
|
+
# point = Ryo(x: 0, y: 0, print: Ryo.fn { print x, y, "\n" })
|
12
|
+
# point.print.()
|
13
|
+
#
|
14
|
+
# @param [Proc] b
|
15
|
+
# The function's body.
|
16
|
+
#
|
17
|
+
# @return [Ryo::Function]
|
18
|
+
# Returns a Ryo function.
|
19
|
+
#
|
20
|
+
# @see Ryo::Function Ryo::Function
|
21
|
+
def fn(&b)
|
22
|
+
Ryo::Function.new(&b)
|
23
|
+
end
|
24
|
+
alias_method :function, :fn
|
25
|
+
|
26
|
+
##
|
27
|
+
# Equivalent to JavaScript's **in** operator.
|
28
|
+
#
|
29
|
+
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
30
|
+
# A Ryo object.
|
31
|
+
#
|
32
|
+
# @param [<String, #to_s>] property
|
33
|
+
# A property name.
|
34
|
+
#
|
35
|
+
# @return [Boolean]
|
36
|
+
# Returns true when **property** is a member of **ryo**, or its prototype chain.
|
37
|
+
def in?(ryo, property)
|
38
|
+
return false unless ryo
|
39
|
+
property?(ryo, property) || in?(prototype_of(ryo), property)
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# The {#delete} method deletes a property from a Ryo object.
|
44
|
+
# More or less equivalent to JavaScript's "delete" operator.
|
45
|
+
#
|
46
|
+
# @note
|
47
|
+
# This method does not delete properties from the prototype(s)
|
48
|
+
# of a Ryo object. <br>
|
49
|
+
# For that - see {Ryo::Reflect#delete! Ryo::Reflect#delete!}.
|
50
|
+
#
|
51
|
+
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
52
|
+
# A Ryo object.
|
53
|
+
#
|
54
|
+
# @param [<String, #to_s>] property
|
55
|
+
# A property name.
|
56
|
+
#
|
57
|
+
# @return [void]
|
58
|
+
def delete(ryo, property)
|
59
|
+
property = property.to_s
|
60
|
+
if property?(ryo, property)
|
61
|
+
table_of(ryo).delete(property)
|
62
|
+
else
|
63
|
+
return if getter_defined?(ryo, property)
|
64
|
+
define_method!(ryo, property) { ryo[property] }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/ryo/lazy.rb
ADDED
data/lib/ryo/object.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# {Ryo::Object Ryo::Object} is a Ryo object and subclass of
|
5
|
+
# Ruby's Object class that can be created by using
|
6
|
+
# [Ryo()](https://0x1eef.github.io/x/ryo.rb/top-level-namespace.html#Ryo-instance_method),
|
7
|
+
# {Ryo.Object Ryo.Object()}, {Ryo::Object.from Ryo::Object.from},
|
8
|
+
# or {Ryo::Object.create Ryo::Object.create}.
|
9
|
+
class Ryo::Object
|
10
|
+
##
|
11
|
+
# @param props (see Ryo::Builder.build)
|
12
|
+
# @param prototype (see Ryo::Builder.build)
|
13
|
+
#
|
14
|
+
# @return [Ryo::Object]
|
15
|
+
# Returns an instance of {Ryo::Object Ryo::Object}.
|
16
|
+
def self.create(props, prototype = nil)
|
17
|
+
Ryo::Builder.build(self, props, prototype)
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Creates a Ryo object by recursively walking a Hash object.
|
22
|
+
#
|
23
|
+
# @param props (see Ryo::Builder.recursive_build)
|
24
|
+
# @param prototype (see Ryo::Builder.recursive_build)
|
25
|
+
#
|
26
|
+
# @return [Ryo::Object]
|
27
|
+
# Returns an instance of {Ryo::Object Ryo::Object}.
|
28
|
+
def self.from(props, prototype = nil)
|
29
|
+
Ryo::Builder.recursive_build(self, props, prototype)
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Duplicates the internals of a Ryo object.
|
34
|
+
#
|
35
|
+
# @param [Ryo::Object] ryo
|
36
|
+
# A Ryo object.
|
37
|
+
#
|
38
|
+
# @return [Ryo::Object]
|
39
|
+
# Returns a Ryo object.
|
40
|
+
def initialize_dup(ryo)
|
41
|
+
Ryo.set_table_of(self, Ryo.table_of(ryo).dup)
|
42
|
+
Ryo.extend!(self, Ryo)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# @example
|
48
|
+
# point = Ryo::Object(x: 0, y: 0)
|
49
|
+
# p [point.x, point.y] # => [0, 0]
|
50
|
+
#
|
51
|
+
# @param props (see Ryo::Builder.build)
|
52
|
+
# @param prototype (see Ryo::Builder.build)
|
53
|
+
#
|
54
|
+
# @return [Ryo::Object]
|
55
|
+
# Returns an instance of {Ryo::Object Ryo::Object}.
|
56
|
+
def Ryo.Object(props, prototype = nil)
|
57
|
+
Ryo::Object.create(props, prototype)
|
58
|
+
end
|