y_support 2.1.18 → 2.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 +4 -4
- data/lib/y_support/all.rb +2 -32
- data/lib/y_support/core_ext/array.rb +2 -2
- data/lib/y_support/core_ext/class.rb +2 -2
- data/lib/y_support/core_ext/enumerable.rb +2 -2
- data/lib/y_support/core_ext/hash/misc.rb +23 -10
- data/lib/y_support/core_ext/hash.rb +2 -2
- data/lib/y_support/core_ext/module/misc.rb +9 -0
- data/lib/y_support/core_ext/module.rb +2 -2
- data/lib/y_support/core_ext/numeric.rb +2 -2
- data/lib/y_support/core_ext/object/inspection.rb +8 -2
- data/lib/y_support/core_ext/object.rb +3 -3
- data/lib/y_support/core_ext/string/misc.rb +9 -12
- data/lib/y_support/core_ext/string.rb +2 -2
- data/lib/y_support/core_ext/symbol.rb +2 -2
- data/lib/y_support/core_ext.rb +1 -1
- data/lib/y_support/flex_coerce/class_methods.rb +49 -0
- data/lib/y_support/flex_coerce/flex_proxy.rb +121 -0
- data/lib/y_support/flex_coerce/module_methods.rb +37 -0
- data/lib/y_support/flex_coerce.rb +24 -0
- data/lib/y_support/kde.rb +1 -1
- data/lib/y_support/literate.rb +253 -0
- data/lib/y_support/local_object.rb +1 -1
- data/lib/y_support/name_magic/array_methods.rb +48 -0
- data/lib/y_support/name_magic/class_methods.rb +205 -161
- data/lib/y_support/name_magic/hash_methods.rb +33 -0
- data/lib/y_support/name_magic/namespace.rb +449 -0
- data/lib/y_support/name_magic.rb +358 -100
- data/lib/y_support/null_object.rb +1 -1
- data/lib/y_support/respond_to.rb +1 -1
- data/lib/y_support/stdlib_ext/matrix/misc.rb +2 -2
- data/lib/y_support/stdlib_ext/matrix.rb +2 -2
- data/lib/y_support/stdlib_ext.rb +1 -1
- data/lib/y_support/typing/array.rb +1 -1
- data/lib/y_support/typing/enumerable.rb +1 -1
- data/lib/y_support/typing/hash.rb +1 -1
- data/lib/y_support/typing/module.rb +1 -1
- data/lib/y_support/typing/object/typing.rb +17 -15
- data/lib/y_support/typing/object.rb +1 -1
- data/lib/y_support/typing.rb +14 -10
- data/lib/y_support/unicode.rb +1 -1
- data/lib/y_support/version.rb +1 -1
- data/lib/y_support/x.rb +2 -1
- data/test/flex_coerce_test.rb +134 -0
- data/test/literate_test.rb +231 -0
- data/test/misc_test.rb +49 -27
- data/test/name_magic_test.rb +907 -60
- data/test/typing_test.rb +7 -7
- metadata +14 -13
- data/lib/y_support/abstract_algebra.rb +0 -234
- data/lib/y_support/name_magic/array.rb +0 -38
- data/lib/y_support/name_magic/hash.rb +0 -31
- data/lib/y_support/name_magic/namespace_methods.rb +0 -260
- data/lib/y_support/try.rb +0 -133
- data/test/abstract_algebra_test.rb +0 -138
- data/test/performance_test_example.rb +0 -23
- data/test/try_test.rb +0 -102
data/lib/y_support/name_magic.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
require_relative '../y_support'
|
4
|
+
require_relative 'core_ext/hash/misc'
|
5
|
+
require_relative 'literate'
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
7
|
+
# Module NameMagic imitates Ruby constant magic and automates the
|
8
|
+
# named argument :name, alias :ɴ (Character "ɴ", Unicode small
|
9
|
+
# capital N). At the same time, NameMagic provides the registry of
|
10
|
+
# instances of the user class. In Ruby, we frequently want to keep
|
11
|
+
# a list of instances of some classes, and NameMagic also helps
|
12
|
+
# with this task. Simple example:
|
12
13
|
#
|
13
14
|
# require 'y_support/name_magic'
|
14
|
-
# class Foo
|
15
|
+
# class Foo
|
15
16
|
# include NameMagic
|
16
17
|
# end
|
17
18
|
# Bar = Foo.new
|
@@ -20,78 +21,162 @@ require_relative 'name_magic/hash'
|
|
20
21
|
#
|
21
22
|
# Bar.name #=> "Bar"
|
22
23
|
#
|
23
|
-
#
|
24
|
-
# defined in the namespace mixin. (Once the object is named, its assignments to
|
25
|
-
# other constants have no further effects.) By default, the class, in which
|
26
|
-
# NameMagic is included acts as a namespace: holds a list of instances and their
|
27
|
-
# names, which is often useful.
|
24
|
+
# We can get the list of instances by:
|
28
25
|
#
|
29
26
|
# Foo.instances #=> [Bar]
|
30
27
|
#
|
31
|
-
#
|
28
|
+
# Additionally, NameMagic provides two hooks: Instantiation hook
|
29
|
+
# activates when a new instance is created, and naming hook
|
30
|
+
# activates when the created instance is baptized. Let us set the
|
31
|
+
# first hook, for example, as follows:
|
32
32
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
33
|
+
# Foo.instantiation_hook do |instance|
|
34
|
+
# puts "New instance of Foo with object id " +
|
35
|
+
# "#{instance.object_id} created!"
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# Now let us set the second hook as follows:
|
39
|
+
#
|
40
|
+
# Foo.naming_hook do |name, instance|
|
41
|
+
# puts "Instance with object id #{instance.object_id} " +
|
42
|
+
# "is baptized #{name}!"
|
43
|
+
# name
|
36
44
|
# end
|
37
|
-
# FooBar.namespace = Quux
|
38
|
-
# FooBar.new name: "Baz"
|
39
|
-
# Quux.instances #=> [Baz]
|
40
45
|
#
|
41
|
-
#
|
42
|
-
#
|
46
|
+
# Note that the naming hook must always return name. (This can be
|
47
|
+
# used to censor the name on the fly, but that's beyond this basic
|
48
|
+
# intro.) Now that we set the hooks, let us observe when do they
|
49
|
+
# activate:
|
50
|
+
#
|
51
|
+
# i = Foo.new
|
52
|
+
# New instance of Foo with object id 73054440 created!
|
53
|
+
#
|
54
|
+
# Baz = i
|
55
|
+
# Instance with object id 73054440 is baptized Baz!
|
56
|
+
#
|
57
|
+
# We can see that the registry of instances now registers two
|
58
|
+
# instances:
|
59
|
+
#
|
60
|
+
# Foo.instances #=> [Bar, Baz]
|
61
|
+
#
|
62
|
+
# NameMagic has been programmed to be simple and intuitive to use,
|
63
|
+
# so with this little demonstration, you can start using it without
|
64
|
+
# fear. You can find the rest of the methods provided by NameMagic
|
65
|
+
# in the documentation.
|
66
|
+
#
|
67
|
+
# However, behind the scenes, inner workings of NameMagic require
|
68
|
+
# understanding. The key part of NameMagic is the code that
|
69
|
+
# searches Ruby namespace for constants. This search is done
|
70
|
+
# automatically when necessary. It can be also explicitly initiated
|
71
|
+
# by calling .const_magic class method, but this is rarely
|
72
|
+
# needed. When you write "include NameMagic" in some class, three
|
73
|
+
# things happen:
|
74
|
+
#
|
75
|
+
# 1. Module NameMagic is included in that class, as expected.
|
76
|
+
# 2. Class is extended with NameMagic::ClassMethods.
|
77
|
+
# 3. Namespace is extended with NameMagic::NamespaceMethods.
|
78
|
+
#
|
79
|
+
# Namespace (in the NameMagic sense) is a module that holds the
|
80
|
+
# list of instances and their names. Typically, the user class acts
|
81
|
+
# as its own namespace. Note that the meaning of the word
|
82
|
+
# 'namespace' is somewhat different from its meaning in general
|
83
|
+
# Ruby. NameMagic actually provides class method .namespace that
|
84
|
+
# returns the namespace of the class. Consider this example:
|
85
|
+
#
|
86
|
+
# require 'y_support/name_magic'
|
87
|
+
# class Animal
|
88
|
+
# include NameMagic
|
89
|
+
# end
|
90
|
+
# Animal.namespace #=> Animal
|
91
|
+
#
|
92
|
+
# We can see that the namespace of Animal class is again Animal
|
93
|
+
# class. But when we subclass it:
|
43
94
|
#
|
44
|
-
# class Animal; include NameMagic end
|
45
95
|
# class Dog < Animal; end
|
46
96
|
# class Cat < Animal; end
|
47
97
|
# Dog.namespace #=> Animal
|
48
98
|
# Cat.namespace #=> Animal
|
99
|
+
#
|
100
|
+
# The subclasses retain Animal as their namespace. Let us continue
|
101
|
+
# with the example:
|
102
|
+
#
|
49
103
|
# Livia = Cat.new
|
50
|
-
# Cat.instances
|
51
|
-
#
|
104
|
+
# Cat.instances #=> [Livia]
|
105
|
+
# Dog.instances #=> []
|
106
|
+
# Animal.instances #=> [Livia]
|
107
|
+
#
|
108
|
+
# Let us demonstrate alternative ways of creating named objects:
|
109
|
+
#
|
110
|
+
# Dog.new name: :Spot
|
111
|
+
# Dog.new ɴ: "Rover"
|
112
|
+
# Cat.instances #=> [Livia]
|
113
|
+
# Dog.instances #=> [Spot, Rover]
|
114
|
+
# Animal.instances #=> [Livia, Spot, Rover]
|
52
115
|
#
|
53
|
-
#
|
116
|
+
# Make the subclasses be their own namespaces with +#namespace!:
|
54
117
|
#
|
55
118
|
# Dog.namespace!
|
56
119
|
#
|
57
|
-
# NameMagic also provides
|
58
|
-
# care of :name (alias :ɴ)
|
120
|
+
# NameMagic also provides another way of naming objects by taking
|
121
|
+
# care of :name (alias :ɴ) parameter of #new constructor:
|
59
122
|
#
|
60
123
|
# Dog.new name: "Spot"
|
61
|
-
# Dog.new
|
124
|
+
# Dog.new.name = :Rover
|
62
125
|
# Dog.instances._names_ #=> [:Spot, :Rover]
|
63
126
|
# Animal.instances._names_ #=> []
|
64
127
|
#
|
65
|
-
#
|
128
|
+
# Note that the Dog instances above did not disappear even though
|
129
|
+
# we did not assign them to any variables or constants. This is
|
130
|
+
# because the instances of the classes using NameMagic, whether
|
131
|
+
# named or not, are since their creation referred to from the
|
132
|
+
# instance registry, which prevents them from being garbage
|
133
|
+
# collected. To get rid of Spot and Rover, we would have to delete
|
134
|
+
# them from the instance registry:
|
66
135
|
#
|
67
|
-
#
|
68
|
-
#
|
136
|
+
# Dog.forget "Spot"
|
137
|
+
# Dog.forget "Rover"
|
69
138
|
#
|
70
|
-
#
|
71
|
-
#
|
139
|
+
# Spot and Rover show their inspect string for the last time and
|
140
|
+
# are garbage collected.
|
72
141
|
#
|
73
142
|
module NameMagic
|
74
|
-
|
143
|
+
require_relative 'name_magic/array_methods'
|
144
|
+
require_relative 'name_magic/hash_methods'
|
75
145
|
|
76
|
-
|
146
|
+
Array.class_exec { include ArrayMethods }
|
147
|
+
Hash.class_exec { include HashMethods }
|
148
|
+
|
149
|
+
require_relative 'name_magic/namespace'
|
77
150
|
require_relative 'name_magic/class_methods'
|
78
151
|
|
79
152
|
def self.included target
|
80
|
-
if target.is_a? Class then
|
153
|
+
if target.is_a? Class then
|
154
|
+
# Define target.namespace method.
|
81
155
|
target.singleton_class.class_exec do
|
82
|
-
# Primer that sets the namespace of the class to self if
|
83
|
-
# not defined otherwise when this method is
|
156
|
+
# Primer that sets the namespace of the class to self if
|
157
|
+
# the user has not defined otherwise when this method is
|
158
|
+
# first called.
|
84
159
|
#
|
85
160
|
define_method :namespace do
|
86
|
-
target.
|
87
|
-
|
161
|
+
# The method first extends target with Namespace methods.
|
162
|
+
target.extend NameMagic::Namespace
|
163
|
+
# The method then redefines itself.
|
164
|
+
define_singleton_method :namespace do target end
|
165
|
+
# And finally calls the redefined version of itself.
|
88
166
|
namespace
|
89
167
|
end
|
90
168
|
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
169
|
+
# Prepend NameMagic::ClassMethod to class << target.
|
170
|
+
target.singleton_class.class_exec do
|
171
|
+
prepend NameMagic::ClassMethods
|
172
|
+
end
|
173
|
+
else # Target is a Module, infect it with this #include
|
174
|
+
original_included_method = target.method :included
|
175
|
+
this_method = method :included
|
176
|
+
target.define_singleton_method :included do |target|
|
177
|
+
this_method.( target )
|
178
|
+
original_included_method.( target )
|
179
|
+
end
|
95
180
|
end
|
96
181
|
end # self.included
|
97
182
|
|
@@ -101,67 +186,143 @@ module NameMagic
|
|
101
186
|
self.class.namespace
|
102
187
|
end
|
103
188
|
|
104
|
-
# Retrieves the instance's name
|
105
|
-
#
|
106
|
-
#
|
189
|
+
# Retrieves the demodulized instance's name as a symbol.
|
190
|
+
# "Demodulized" means that if the full name is "Foo::Bar", only
|
191
|
+
# :Bar is returned. Underlines (+#_name_+) distinguish this
|
192
|
+
# method from +#name+ method, which returns full name string for
|
193
|
+
# compatibility with vanilla Ruby +Module#name+.
|
107
194
|
#
|
108
195
|
def _name_
|
109
196
|
self.class.const_magic
|
110
197
|
__name__ or ( yield self if block_given? )
|
111
198
|
end
|
112
199
|
alias ɴ _name_
|
113
|
-
# FIXME: Delete the line below! Do it! Make #name return
|
200
|
+
# FIXME: Delete the line below! Do it! Make #name return
|
201
|
+
# #full_name, as compatible with Class#name behavior!!!
|
114
202
|
alias name _name_
|
115
203
|
|
116
|
-
# Returns the instance's full name, a string in the style of
|
117
|
-
# by +Module#name+ method, eg. "Namespace::Name".
|
204
|
+
# Returns the instance's full name, a string in the style of
|
205
|
+
# those returned by +Module#name+ method, eg. "Namespace::Name".
|
118
206
|
#
|
119
207
|
def full_name
|
120
|
-
|
208
|
+
# FIXME: This method cannot work until Namespace#const_magic
|
209
|
+
# starts noticing not just constant names, as it does now,
|
210
|
+
# but also names of the modules those constants are in. This
|
211
|
+
# is no simple task.
|
212
|
+
#
|
213
|
+
# The code below is the closest approximation, yet still
|
214
|
+
# patently wrong.
|
215
|
+
[ namespace.name || namespace.inspect,
|
216
|
+
namespace.instances[ self ]
|
217
|
+
].join "::"
|
121
218
|
end
|
122
|
-
# FIXME: Uncomment the line below! Do it! Make #name return
|
123
|
-
#
|
219
|
+
# FIXME: Uncomment the line below! Do it! Make #name return
|
220
|
+
# #full_name, as compatible with Class#name behavior!!! alias
|
221
|
+
# name full_name
|
124
222
|
|
125
|
-
# Retrieves the instance name. Does not trigger #const_magic
|
223
|
+
# Retrieves the instance name. Does not trigger #const_magic
|
224
|
+
# before doing so.
|
126
225
|
#
|
127
226
|
def __name__
|
128
|
-
|
129
|
-
namespace.name_get_hook.( ɴ ) if ɴ
|
227
|
+
self.class.__instances__[ self ]
|
130
228
|
end
|
131
229
|
|
132
|
-
# Names
|
230
|
+
# Names the receiver, while rejecting names already in use by
|
231
|
+
# another instance. If nil is supplied as an argument, unnames
|
232
|
+
# the instance. (This method does not trigger const_magic.)
|
133
233
|
#
|
134
234
|
def name=( name )
|
135
|
-
|
136
|
-
if name.nil?
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
235
|
+
# If the argument is nil, the method performs unnaming.
|
236
|
+
return unname! if name.nil?
|
237
|
+
# Otherwise, the method performs naming the instance, while
|
238
|
+
# avoiding stealing names already in use by another instance.
|
239
|
+
# Let us look at the current name of the instance first.
|
240
|
+
previous_name = namespace.__instances__[ self ]
|
241
|
+
# Honor class'es #exec_when_naming hook.
|
242
|
+
requested_new_name = honor_exec_when_naming( name )
|
243
|
+
# Return if the instance is already named as requested.
|
244
|
+
return if previous_name == requested_new_name
|
245
|
+
# Raise error if the requested name is already taken.
|
246
|
+
self.class.__instances__.rassoc( requested_new_name ) and
|
247
|
+
fail NameError, "Name '#{requested_new_name}' already " +
|
248
|
+
"exists in #{namespace} namespace!"
|
249
|
+
# Now it is sure that the instance will be named, so it does
|
250
|
+
# not need to be avid.
|
251
|
+
make_not_avid!
|
252
|
+
# Rename self by modifying the registry.
|
253
|
+
namespace.__instances__.update self => requested_new_name
|
254
|
+
# Honor instance's #exec_when_named hook.
|
255
|
+
honor_exec_when_named
|
148
256
|
end
|
149
257
|
|
150
|
-
# Names
|
258
|
+
# Names the receiver aggresively. "Aggresively" means that in
|
259
|
+
# case the requested new name of the instance is already in use
|
260
|
+
# by another instance, the other instance is unnamed. In other
|
261
|
+
# words, in case of conflict of a name, the name is stolen from
|
262
|
+
# the conflicting instance, which becomes unnamed as a result.
|
263
|
+
# (The method does not trigger const_magic.)
|
151
264
|
#
|
152
265
|
def name!( name )
|
153
|
-
|
154
|
-
return
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
namespace.
|
160
|
-
|
161
|
-
|
266
|
+
# If the argument is nil, the method performs unnaming.
|
267
|
+
return unname! if name.nil?
|
268
|
+
# Otherwise, the method performs aggresive naming the instance,
|
269
|
+
# where "aggresive" means that in case of conflict over a name,
|
270
|
+
# the name is stolen from the conflicting instance.
|
271
|
+
# Let us look at the current name of the instance first.
|
272
|
+
previous_name = namespace.__instances__[ self ]
|
273
|
+
# Honor class'es #exec_when_naming hook.
|
274
|
+
requested_new_name = honor_exec_when_naming( name )
|
275
|
+
# Return if the instance is already named as requested.
|
276
|
+
return if previous_name == requested_new_name
|
277
|
+
# See if the requested name is already taken.
|
278
|
+
colliding_entry =
|
279
|
+
namespace.__instances__.rassoc( requested_new_name )
|
280
|
+
# Unname the colliding instance, if any.
|
281
|
+
begin
|
282
|
+
colliding_entry.first.unname! if colliding_entry
|
283
|
+
ensure
|
284
|
+
# Unnaming the colliding instance may fail. But whether it
|
285
|
+
# fails or succeeds, self must quit being avid. If the
|
286
|
+
# unnaming succeeded, self is getting a new name and thus
|
287
|
+
# no longer needs to be avid. However, if the unnaming
|
288
|
+
# raises an error, we want to avoid seeing the same error
|
289
|
+
# over and over again just because avid self assigned to
|
290
|
+
# a constant with conflicting name tries over and over again
|
291
|
+
# to perform the impossible feat of stealing that name.
|
292
|
+
make_not_avid!
|
293
|
+
end
|
294
|
+
# Rename self by modifying the registry.
|
295
|
+
namespace.__instances__.update self => requested_new_name
|
296
|
+
# Honor instance's #exec_when_named hook.
|
297
|
+
honor_exec_when_named
|
298
|
+
# Return the receiver.
|
299
|
+
return self
|
300
|
+
end
|
301
|
+
|
302
|
+
# Unnames the instance. Does not trigger #const_magic.
|
303
|
+
#
|
304
|
+
def unname!
|
305
|
+
# Get the current name of the instance.
|
306
|
+
name = namespace.__instances__[ self ]
|
307
|
+
# If the instance is anonymous, we are done.
|
308
|
+
return if name.nil?
|
309
|
+
# Check whether unnaming instances is allowed at all.
|
310
|
+
fail NameError, "Unnaming and naming by a name already in " +
|
311
|
+
"use by another instance has been disallowed!" unless
|
312
|
+
unnaming_allowed?
|
313
|
+
# Honor class'es #exec_when_unnaming hook.
|
314
|
+
honor_exec_when_unnaming
|
315
|
+
# Unname the instance by deleting the name from the registry.
|
316
|
+
namespace.__instances__.update( self => nil )
|
317
|
+
# Honor instance's #exec_when_unnamed hook.
|
318
|
+
honor_exec_when_unnamed
|
319
|
+
# Return value is the previous name.
|
320
|
+
return name
|
162
321
|
end
|
163
322
|
|
164
|
-
# Is the instance avid
|
323
|
+
# Is the instance avid? ("Avid" means that the instance is so
|
324
|
+
# eager to get a name that it will use name even if this is
|
325
|
+
# already in use by another instance.)
|
165
326
|
#
|
166
327
|
def avid?
|
167
328
|
namespace.__avid_instances__.any? &method( :equal? )
|
@@ -170,21 +331,48 @@ module NameMagic
|
|
170
331
|
# Make the instance not avid.
|
171
332
|
#
|
172
333
|
def make_not_avid!
|
173
|
-
namespace.__avid_instances__.delete_if { |i| i
|
334
|
+
namespace.__avid_instances__.delete_if { |i| equal? i }
|
335
|
+
return nil
|
336
|
+
end
|
337
|
+
|
338
|
+
# Is unnaming of the instance allowed? Note: This method just
|
339
|
+
# relies on class'es .permanent_names? method. Unnaming is not
|
340
|
+
# allowed when .permanent_names? is true.
|
341
|
+
#
|
342
|
+
def unnaming_allowed?
|
343
|
+
! self.class.permanent_names?
|
344
|
+
end
|
345
|
+
|
346
|
+
# Registers a block to execute as soon as the instance is named.
|
347
|
+
# (In other words, this method provides instance's naming hook.)
|
348
|
+
# The block is executed in the context of the instance. Return
|
349
|
+
# value of the block is unimportant. If no block is given, the
|
350
|
+
# method returns the previously defined block, if any, or a
|
351
|
+
# default block that does nothing.
|
352
|
+
#
|
353
|
+
def exec_when_named &block
|
354
|
+
@exec_when_named = block if block
|
355
|
+
@exec_when_named ||= -> { }
|
174
356
|
end
|
357
|
+
# Note: This alias must stay while the dependencies need it.
|
358
|
+
alias name_set_hook exec_when_named
|
175
359
|
|
176
|
-
# Registers a
|
177
|
-
#
|
178
|
-
#
|
179
|
-
#
|
180
|
-
#
|
360
|
+
# Registers a block to execute right after the instance is
|
361
|
+
# unnamed. (In other words, this method provides instance's
|
362
|
+
# unnaming hook.) The block is executed in the context of the
|
363
|
+
# instance. Return value of the block is unimportant. If no block
|
364
|
+
# is given, the method returns the previously defined block, if
|
365
|
+
# any, or a default block that does nothing.
|
181
366
|
#
|
182
|
-
def
|
183
|
-
|
184
|
-
@
|
367
|
+
def exec_when_unnamed &block
|
368
|
+
@exec_when_unnamed = block if block
|
369
|
+
@exec_when_unnamed ||= -> { }
|
185
370
|
end
|
371
|
+
# Note: This alias must stay while the dependencies need it.
|
372
|
+
alias name_set_hook exec_when_named
|
186
373
|
|
187
|
-
#
|
374
|
+
# +NameMagic+ redefines #to_s method to show names.
|
375
|
+
# name.
|
188
376
|
#
|
189
377
|
def to_s
|
190
378
|
name ? name.to_s : super
|
@@ -198,13 +386,83 @@ module NameMagic
|
|
198
386
|
|
199
387
|
private
|
200
388
|
|
201
|
-
#
|
202
|
-
#
|
203
|
-
#
|
389
|
+
# Make the instance avid. Does not trigger const_magic. (Remark:
|
390
|
+
# Invoking this method on named instances is considered gross
|
391
|
+
# indecency.)
|
392
|
+
#
|
393
|
+
def make_avid!
|
394
|
+
namespace.__avid_instances__ << self unless
|
395
|
+
namespace.__avid_instances__.include? self
|
396
|
+
return nil
|
397
|
+
end
|
398
|
+
|
399
|
+
# Honors the class'es hook #exec_when_naming. Takes 2
|
400
|
+
# arguments, name and old name of this instance. Also calls
|
401
|
+
# Namespace#validate_name method. Returns the final name to be
|
402
|
+
# used.
|
403
|
+
#
|
404
|
+
def honor_exec_when_naming( suggested_name )
|
405
|
+
instance = self
|
406
|
+
previous_name = namespace.__instances__[ instance ]
|
407
|
+
suggested_name = suggested_name.to_s
|
408
|
+
# Calling exec_when_naming without a block makes the method
|
409
|
+
# return the block defined earlier.
|
410
|
+
block = self.class.exec_when_naming
|
411
|
+
# Execute the namespace hook in the context of the user class.
|
412
|
+
name = self.class.instance_exec( suggested_name,
|
413
|
+
instance,
|
414
|
+
previous_name,
|
415
|
+
&block )
|
416
|
+
# The hook is supposed to return the name to be actually used.
|
417
|
+
# But if the user used the block for other purposes and did
|
418
|
+
# not bother to return a string or symbol (or anything that
|
419
|
+
# can be converted to a symbol), we will assume that the user
|
420
|
+
# meant to leave the suggested name without intervention.
|
421
|
+
# I wonder whether this behavior is too smart.
|
422
|
+
name = begin; name.to_sym; rescue NoMethodError
|
423
|
+
suggested_name
|
424
|
+
end
|
425
|
+
# Finally, apply validate_name method and return the result.
|
426
|
+
return self.class.validate_name( name ).to_sym
|
427
|
+
end
|
428
|
+
|
429
|
+
# Honors instance's hook #exec_when_named.
|
430
|
+
#
|
431
|
+
def honor_exec_when_named
|
432
|
+
# Method #exec_when_named, when called without a block, returns
|
433
|
+
# the block defined earlier.
|
434
|
+
block = exec_when_named
|
435
|
+
# Block is executed within the context of this instance.
|
436
|
+
instance_exec &block
|
437
|
+
# The method returns nil.
|
438
|
+
return nil
|
439
|
+
end
|
440
|
+
|
441
|
+
# Honors the class'es hook #exec_when_unnaming.
|
442
|
+
#
|
443
|
+
def honor_exec_when_unnaming
|
444
|
+
instance = self
|
445
|
+
previous_name = namespace.__instances__[ instance ]
|
446
|
+
# Calling exec_when_unnaming without a block makes the method
|
447
|
+
# return the block defined earlier.
|
448
|
+
block = self.class.exec_when_unnaming
|
449
|
+
# Execute the namespace hook in the context of the user class.
|
450
|
+
name = self.class.instance_exec( instance,
|
451
|
+
previous_name,
|
452
|
+
&block )
|
453
|
+
# The method returns nil.
|
454
|
+
return nil
|
455
|
+
end
|
456
|
+
|
457
|
+
# Honors instance's hook #exec_when_unnamed.
|
204
458
|
#
|
205
|
-
def
|
206
|
-
|
207
|
-
#
|
208
|
-
|
459
|
+
def honor_exec_when_unnamed
|
460
|
+
# Method #exec_when_unnamed, when called without a block,
|
461
|
+
# returns the block defined earlier.
|
462
|
+
block = exec_when_unnamed
|
463
|
+
# Block is executed within the context of this instance.
|
464
|
+
instance_exec &block
|
465
|
+
# The method returns nil.
|
466
|
+
return nil
|
209
467
|
end
|
210
468
|
end # module NameMagic
|
data/lib/y_support/respond_to.rb
CHANGED
@@ -5,7 +5,7 @@ class Matrix
|
|
5
5
|
def pretty_inspect
|
6
6
|
return inspect if row_size == 0 or column_size == 0
|
7
7
|
aa = send( :rows ).each.with_object [] do |row, memo|
|
8
|
-
memo << row.map{ |o|
|
8
|
+
memo << row.map { |o|
|
9
9
|
os = o.to_s
|
10
10
|
case o
|
11
11
|
when Numeric then os[0] == '-' ? os : ' ' + os
|
@@ -18,7 +18,7 @@ class Matrix
|
|
18
18
|
memo << "\n"
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
# Pretty print
|
23
23
|
def pretty_print
|
24
24
|
print pretty_inspect
|
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative '../../y_support'
|
2
|
+
require_relative 'matrix/misc'
|
data/lib/y_support/stdlib_ext.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
require_relative 'array/typing'
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
require_relative 'enumerable/typing'
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
require_relative 'hash/typing'
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
require_relative 'module/typing'
|