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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/y_support/all.rb +2 -32
  3. data/lib/y_support/core_ext/array.rb +2 -2
  4. data/lib/y_support/core_ext/class.rb +2 -2
  5. data/lib/y_support/core_ext/enumerable.rb +2 -2
  6. data/lib/y_support/core_ext/hash/misc.rb +23 -10
  7. data/lib/y_support/core_ext/hash.rb +2 -2
  8. data/lib/y_support/core_ext/module/misc.rb +9 -0
  9. data/lib/y_support/core_ext/module.rb +2 -2
  10. data/lib/y_support/core_ext/numeric.rb +2 -2
  11. data/lib/y_support/core_ext/object/inspection.rb +8 -2
  12. data/lib/y_support/core_ext/object.rb +3 -3
  13. data/lib/y_support/core_ext/string/misc.rb +9 -12
  14. data/lib/y_support/core_ext/string.rb +2 -2
  15. data/lib/y_support/core_ext/symbol.rb +2 -2
  16. data/lib/y_support/core_ext.rb +1 -1
  17. data/lib/y_support/flex_coerce/class_methods.rb +49 -0
  18. data/lib/y_support/flex_coerce/flex_proxy.rb +121 -0
  19. data/lib/y_support/flex_coerce/module_methods.rb +37 -0
  20. data/lib/y_support/flex_coerce.rb +24 -0
  21. data/lib/y_support/kde.rb +1 -1
  22. data/lib/y_support/literate.rb +253 -0
  23. data/lib/y_support/local_object.rb +1 -1
  24. data/lib/y_support/name_magic/array_methods.rb +48 -0
  25. data/lib/y_support/name_magic/class_methods.rb +205 -161
  26. data/lib/y_support/name_magic/hash_methods.rb +33 -0
  27. data/lib/y_support/name_magic/namespace.rb +449 -0
  28. data/lib/y_support/name_magic.rb +358 -100
  29. data/lib/y_support/null_object.rb +1 -1
  30. data/lib/y_support/respond_to.rb +1 -1
  31. data/lib/y_support/stdlib_ext/matrix/misc.rb +2 -2
  32. data/lib/y_support/stdlib_ext/matrix.rb +2 -2
  33. data/lib/y_support/stdlib_ext.rb +1 -1
  34. data/lib/y_support/typing/array.rb +1 -1
  35. data/lib/y_support/typing/enumerable.rb +1 -1
  36. data/lib/y_support/typing/hash.rb +1 -1
  37. data/lib/y_support/typing/module.rb +1 -1
  38. data/lib/y_support/typing/object/typing.rb +17 -15
  39. data/lib/y_support/typing/object.rb +1 -1
  40. data/lib/y_support/typing.rb +14 -10
  41. data/lib/y_support/unicode.rb +1 -1
  42. data/lib/y_support/version.rb +1 -1
  43. data/lib/y_support/x.rb +2 -1
  44. data/test/flex_coerce_test.rb +134 -0
  45. data/test/literate_test.rb +231 -0
  46. data/test/misc_test.rb +49 -27
  47. data/test/name_magic_test.rb +907 -60
  48. data/test/typing_test.rb +7 -7
  49. metadata +14 -13
  50. data/lib/y_support/abstract_algebra.rb +0 -234
  51. data/lib/y_support/name_magic/array.rb +0 -38
  52. data/lib/y_support/name_magic/hash.rb +0 -31
  53. data/lib/y_support/name_magic/namespace_methods.rb +0 -260
  54. data/lib/y_support/try.rb +0 -133
  55. data/test/abstract_algebra_test.rb +0 -138
  56. data/test/performance_test_example.rb +0 -23
  57. data/test/try_test.rb +0 -102
@@ -1,17 +1,18 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'y_support'
4
- require 'y_support/core_ext/hash/misc'
3
+ require_relative '../y_support'
4
+ require_relative 'core_ext/hash/misc'
5
+ require_relative 'literate'
5
6
 
6
- require_relative 'name_magic/array'
7
- require_relative 'name_magic/hash'
8
-
9
- # This mixin imitates Ruby constant magic and automates the named argument
10
- # :name, alias (Character "ɴ", Unicode small capital N, generally stands
11
- # for "name" ins YSupport). One can write:
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
- # This is done by searching whole Ruby namespace for constants, via #const_magic
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
- # It is possible to set another module as namespace:
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
- # Quux = Module.new
34
- # class FooBar
35
- # include NameMagic
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
- # When subclassing the classes with NameMagic included, namespace setting does
42
- # not change:
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._names_ #=> []
51
- # Animal.instances._names_ #=> [:Livia]
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
- # To make the subclasses use each their own namespace, use +#namespace!+ method:
116
+ # Make the subclasses be their own namespaces with +#namespace!:
54
117
  #
55
118
  # Dog.namespace!
56
119
  #
57
- # NameMagic also provides an alternative way to create named objects by taking
58
- # care of :name (alias :ɴ) named argument of the constructor:
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 ɴ: :Rover
124
+ # Dog.new.name = :Rover
62
125
  # Dog.instances._names_ #=> [:Spot, :Rover]
63
126
  # Animal.instances._names_ #=> []
64
127
  #
65
- # Lastly, a name can be assigned by #name= accssor, as in
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
- # <tt>o = SomeClass.new</tt>
68
- # <tt>o.name = "SomeName"</tt>
136
+ # Dog.forget "Spot"
137
+ # Dog.forget "Rover"
69
138
  #
70
- # Hook is provided for when the name magic is performed, as well as when the
71
- # name is retrieved.
139
+ # Spot and Rover show their inspect string for the last time and
140
+ # are garbage collected.
72
141
  #
73
142
  module NameMagic
74
- DEBUG = false
143
+ require_relative 'name_magic/array_methods'
144
+ require_relative 'name_magic/hash_methods'
75
145
 
76
- require_relative 'name_magic/namespace_methods'
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 # decorate #new
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 the user has
83
- # not defined otherwise when this method is first called.
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.extend ::NameMagic::NamespaceMethods
87
- define_singleton_method :namespace do target end # redefines itself
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
- target.singleton_class.class_exec { prepend ::NameMagic::ClassMethods }
92
- else # it is a Module -- infect it with this #include
93
- orig, this = target.method( :included ), method( :included )
94
- target.define_singleton_method :included do |m| this.( m ); orig.( m ) end
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 not prefixed by the namespace as a symbol.
105
- # Underlines (+#_name_+) distinguish this method from +#name+ method, which
106
- # returns full name string for compatibility with vanilla Ruby +Module#name+.
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 #full_name, as compatible with Class#name behavior!!!
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 those returned
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
- "#{namespace.name || namespace.inspect}::#{namespace.instances[ self ]}"
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 #full_name, as compatible with Class#name behavior!!!
123
- # alias name full_name
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 before doing so.
223
+ # Retrieves the instance name. Does not trigger #const_magic
224
+ # before doing so.
126
225
  #
127
226
  def __name__
128
- ɴ = self.class.__instances__[ self ]
129
- namespace.name_get_hook.( ɴ ) if ɴ
227
+ self.class.__instances__[ self ]
130
228
  end
131
229
 
132
- # Names an instance, cautiously (ie. no overwriting of existing 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
- old_ɴ = namespace.__instances__[ self ] # previous name
136
- if name.nil? then
137
- namespace.__instances__.update( self => nil ) # unname in @instances
138
- namespace.send :remove_const, old_ɴ if old_ɴ # remove namespace const.
139
- else
140
- ɴ = honor_name_set_hooks( name, old_ɴ )
141
- return if old_ɴ == ɴ # already named as required
142
- fail NameError, "Name '#{ɴ}' already exists in #{namespace} namespace!" if
143
- self.class.__instances__.rassoc( ɴ )
144
- namespace.__forget__ old_ɴ # forget the old name of self
145
- namespace.const_set ɴ, self # write a constant
146
- namespace.__instances__[ self ] = ɴ # write to @instances
147
- end
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 an instance, aggresively (overwrites existing 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
- old_ɴ = namespace.__instances__[ self ] # previous name
154
- return self.name = nil if name.nil? # no collider concerns
155
- ɴ = honor_name_set_hooks( name, old_ɴ )
156
- return false if old_ɴ == ɴ # already named as required
157
- pair = namespace.__instances__.rassoc( ɴ )
158
- namespace.__forget__( pair[0] ) if pair # rudely forget the collider
159
- namespace.__forget__ old_ɴ # forget the old name of self
160
- namespace.const_set ɴ, self # write a constant
161
- namespace.__instances__[ self ] = ɴ # write to @instances
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 for a name? (Will it overwrite other instance names?)
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.object_id == object_id }
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 hook to execute upon instance naming. Instance's `#name_set_hook`
177
- # Behaves analogically as namespace's `#name_set_hook`, and is executed right
178
- # after the namespace's hook. Expects a block with a single argument, name of
179
- # the instance. The return value of the block is not used and should be _nil_.
180
- # Without a block, this method acts as a getter.
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 name_set_hook &block
183
- tap { @name_set_hook = block } if block
184
- @name_set_hook ||= -> name { nil }
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
- # Default +#to_s+ method for +NameMagic+ includers, returning the name.
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
- # Honors name set hooks, first for the namespace, then for the instance.
202
- # Takes 2 arguments, name and old name of this instance. Returns the final
203
- # name to be used
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 honor_name_set_hooks suggested_name, old_name
206
- ɴ = namespace.name_set_hook.( suggested_name, self, old_name ).to_sym
207
- # puts "NameMagic: Name adjusted to #{name}." if DEBUG
208
- namespace.validate_name( ɴ ).to_sym.tap { |ɴ| name_set_hook.( ɴ ) }
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
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'y_support'
3
+ require_relative '../y_support'
4
4
 
5
5
  # Null object pattern implementation in +YSupport+. apart from the expected null
6
6
  # object behavior (such as returning self in response to almost all messages),
@@ -1,4 +1,4 @@
1
- require 'y_support'
1
+ require_relative '../y_support'
2
2
 
3
3
  # RespondTo class for easy use of respond_to? in case statements.
4
4
  #
@@ -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
- require 'y_support' unless defined? YSupport
2
- require File.dirname( __FILE__ ) + '/matrix/misc'
1
+ require_relative '../../y_support'
2
+ require_relative 'matrix/misc'
@@ -1,4 +1,4 @@
1
1
  Dir["#{File.dirname( __FILE__ )}/stdlib_ext/*.rb"].sort.each do |path|
2
- require "y_support/stdlib_ext/#{File.basename( path, '.rb' )}"
2
+ require_relative "y_support/stdlib_ext/#{File.basename( path, '.rb' )}"
3
3
  end
4
4
 
@@ -1 +1 @@
1
- require File.dirname( __FILE__ ) + '/array/typing'
1
+ require_relative 'array/typing'
@@ -1 +1 @@
1
- require File.dirname( __FILE__ ) + '/enumerable/typing'
1
+ require_relative 'enumerable/typing'
@@ -1 +1 @@
1
- require File.dirname( __FILE__ ) + '/hash/typing'
1
+ require_relative 'hash/typing'
@@ -1 +1 @@
1
- require File.dirname( __FILE__ ) + '/module/typing'
1
+ require_relative 'module/typing'