y_support 2.1.5 → 2.1.12

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +675 -0
  3. data/Rakefile +1 -1
  4. data/lib/y_support/abstract_algebra.rb +1 -0
  5. data/lib/y_support/all.rb +1 -0
  6. data/lib/y_support/core_ext/array.rb +2 -2
  7. data/lib/y_support/core_ext/class/misc.rb +2 -3
  8. data/lib/y_support/core_ext/class.rb +2 -2
  9. data/lib/y_support/core_ext/enumerable/misc.rb +1 -1
  10. data/lib/y_support/core_ext/enumerable.rb +2 -2
  11. data/lib/y_support/core_ext/hash/misc.rb +26 -39
  12. data/lib/y_support/core_ext/hash.rb +2 -2
  13. data/lib/y_support/core_ext/module/misc.rb +39 -1
  14. data/lib/y_support/core_ext/module.rb +2 -2
  15. data/lib/y_support/core_ext/numeric/misc.rb +0 -2
  16. data/lib/y_support/core_ext/numeric.rb +2 -2
  17. data/lib/y_support/core_ext/object/inspection.rb +0 -2
  18. data/lib/y_support/core_ext/object/misc.rb +31 -16
  19. data/lib/y_support/core_ext/object.rb +3 -3
  20. data/lib/y_support/core_ext/string/misc.rb +7 -7
  21. data/lib/y_support/core_ext/string.rb +2 -2
  22. data/lib/y_support/core_ext/symbol/misc.rb +2 -3
  23. data/lib/y_support/core_ext/symbol.rb +2 -2
  24. data/lib/y_support/core_ext.rb +0 -2
  25. data/lib/y_support/inert_recorder.rb +1 -1
  26. data/lib/y_support/kde.rb +1 -0
  27. data/lib/y_support/name_magic/array.rb +27 -7
  28. data/lib/y_support/name_magic/class_methods.rb +52 -58
  29. data/lib/y_support/name_magic/hash.rb +18 -4
  30. data/lib/y_support/name_magic/namespace_methods.rb +241 -174
  31. data/lib/y_support/name_magic.rb +82 -38
  32. data/lib/y_support/null_object.rb +8 -7
  33. data/lib/y_support/respond_to.rb +1 -2
  34. data/lib/y_support/stdlib_ext/matrix/misc.rb +0 -2
  35. data/lib/y_support/stdlib_ext/matrix.rb +2 -2
  36. data/lib/y_support/stdlib_ext.rb +1 -0
  37. data/lib/y_support/try.rb +1 -1
  38. data/lib/y_support/typing/array/typing.rb +45 -4
  39. data/lib/y_support/typing/array.rb +1 -1
  40. data/lib/y_support/typing/enumerable/typing.rb +26 -28
  41. data/lib/y_support/typing/enumerable.rb +1 -1
  42. data/lib/y_support/typing/hash/typing.rb +47 -29
  43. data/lib/y_support/typing/hash.rb +1 -1
  44. data/lib/y_support/typing/module/typing.rb +4 -6
  45. data/lib/y_support/typing/module.rb +1 -1
  46. data/lib/y_support/typing/object/typing.rb +64 -61
  47. data/lib/y_support/typing/object.rb +1 -1
  48. data/lib/y_support/typing.rb +4 -26
  49. data/lib/y_support/unicode.rb +5 -7
  50. data/lib/y_support/version.rb +1 -1
  51. data/lib/y_support/x.rb +11 -8
  52. data/lib/y_support.rb +2 -2
  53. data/test/abstract_algebra_test.rb +44 -55
  54. data/test/inert_recorder_test.rb +13 -18
  55. data/test/local_object_test.rb +13 -18
  56. data/test/misc_test.rb +15 -10
  57. data/test/name_magic_test.rb +1 -1
  58. data/test/null_object_test.rb +19 -26
  59. data/test/respond_to_test.rb +15 -16
  60. data/test/typing_test.rb +100 -103
  61. data/test/x_test.rb +16 -19
  62. data/y_support.gemspec +21 -17
  63. metadata +37 -8
  64. data/LICENSE +0 -22
@@ -231,3 +231,4 @@ class Matrix
231
231
  build r_count, c_count do |r, c| WILDCARD_ZERO end
232
232
  end
233
233
  end
234
+
data/lib/y_support/all.rb CHANGED
@@ -42,3 +42,4 @@ require 'y_support/misc'
42
42
  # end
43
43
  # end
44
44
  # end # class BlankSlate
45
+
@@ -1,2 +1,2 @@
1
- require 'y_support'
2
- require 'y_support/core_ext/array/misc'
1
+ require 'y_support' unless defined? YSupport
2
+ require File.dirname( __FILE__ ) + '/array/misc'
@@ -1,17 +1,16 @@
1
- #encoding: utf-8
2
-
3
1
  class Class
4
2
  # Creates a subclass of the current class parametrized with a given set of
5
3
  # parameters. The parameters have form { symbol: value } and they cause
6
4
  # singleton method(s) named "symbol" be defined on the subclass, returning
7
5
  # "value".
8
6
  #
9
- def parametrize parameters
7
+ def parametrize **parameters, &block
10
8
  Class.new( self ).tap do |subclass|
11
9
  parameters.each_pair { |symbol, value|
12
10
  subclass.define_singleton_method symbol do value end
13
11
  }
14
12
  subclass.define_singleton_method inspect do subclass.superclass.inspect + "<" end
13
+ subclass.class_exec &block if block
15
14
  end
16
15
  end
17
16
  end
@@ -1,2 +1,2 @@
1
- require 'y_support'
2
- require 'y_support/core_ext/class/misc'
1
+ require 'y_support' unless defined? YSupport
2
+ require File.dirname( __FILE__ ) + '/class/misc'
@@ -1,4 +1,4 @@
1
- #encoding: utf-8
1
+ # encoding: utf-8
2
2
 
3
3
  module Enumerable
4
4
  # Checks whether #all? collection elements are #kind_of? module
@@ -1,2 +1,2 @@
1
- require 'y_support'
2
- require 'y_support/core_ext/enumerable/misc'
1
+ require 'y_support' unless defined? YSupport
2
+ require File.dirname( __FILE__ ) + '/enumerable/misc'
@@ -1,10 +1,8 @@
1
- # encoding: utf-8
2
-
3
1
  require 'active_support/core_ext/hash/reverse_merge'
4
2
 
5
3
  class Hash
6
4
  class << self
7
- # This kluge method guards against overwriting of the #slice method by
5
+ # This kludge method guards against overwriting of the #slice method by
8
6
  # ActiveSupport.
9
7
  #
10
8
  def method_added( sym )
@@ -26,11 +24,8 @@ class Hash
26
24
  #
27
25
  define_method sym do |matcher|
28
26
  self.class[ case matcher
29
- when Array then
30
- select { |key, _| matcher.include? key }
31
- else
32
- select { |key, _| matcher === key }
33
- end ]
27
+ when Array then select { |k, _| matcher.include? k }
28
+ else select { |k, _| matcher === k } end ]
34
29
  end
35
30
  end
36
31
 
@@ -49,8 +44,8 @@ class Hash
49
44
  # Applies a block as a mapping on all keys, returning a new hash.
50
45
  #
51
46
  def with_keys
52
- keys.each_with_object self.class.new do |hash_key, hsh|
53
- hsh[ yield hash_key ] = self[ hash_key ]
47
+ keys.each_with_object self.class.new do |key, hsh|
48
+ hsh[ yield key ] = self[ key ]
54
49
  end
55
50
  end
56
51
 
@@ -58,8 +53,8 @@ class Hash
58
53
  # 2 arguments (key: value pair) and returns the new key.
59
54
  #
60
55
  def modify_keys
61
- each_with_object self.class.new do |hash_pair, hsh|
62
- hsh[ yield( hash_pair ) ] = self[ hash_pair[0] ]
56
+ each_with_object self.class.new do |pair, hsh|
57
+ hsh[ yield pair ] = self[ pair[0] ]
63
58
  end
64
59
  end
65
60
 
@@ -79,25 +74,25 @@ class Hash
79
74
  # that takes 2 arguments (key: value pair) and returns the new value.
80
75
  #
81
76
  def modify_values
82
- each_with_object self.class.new do |hash_pair, ꜧ|
83
- [ hash_pair[0] ] = yield( hash_pair )
77
+ each_with_object self.class.new do |pair, hsh|
78
+ hsh[ pair[0] ] = yield pair
84
79
  end
85
80
  end
86
81
 
87
82
  # Like #modify_values, but modifies the receiver.
88
83
  #
89
84
  def modify_values!
90
- each_with_object self do |hash_pair, ꜧ|
91
- [ hash_pair[0] ] = yield( hash_pair )
85
+ each_with_object self do |pair, hsh|
86
+ hsh[ pair[0] ] = yield pair
92
87
  end
93
88
  end
94
89
 
95
90
  # Like #map that returns a hash.
96
91
  #
97
92
  def modify
98
- each_with_object self.class.new do |hash_pair, ꜧ|
99
- key, val = yield hash_pair
100
- [key] = val
93
+ each_with_object self.class.new do |pair, hsh|
94
+ key, val = yield pair
95
+ hsh[key] = val
101
96
  end
102
97
  end
103
98
 
@@ -113,11 +108,8 @@ class Hash
113
108
  #
114
109
  def slice matcher
115
110
  self.class[ case matcher
116
- when Array then
117
- select { |key, _| matcher.include? key }
118
- else
119
- select { |key, _| matcher === key }
120
- end ]
111
+ when Array then select { |key, _| matcher.include? key }
112
+ else select { |key, _| matcher === key } end ]
121
113
  end
122
114
 
123
115
  # Makes hash keys accessible as methods. If the hash keys collide with
@@ -125,31 +117,26 @@ class Hash
125
117
  # option == true.
126
118
  #
127
119
  def dot! overwrite_methods: false
128
- keys.each do |key|
129
- msg = "key #{key} of #dot!-ted hash is not convertible to a symbol"
130
- fail ArgumentError, msg unless key.respond_to? :to_sym
131
- msg = "#dot!-ted hash must not have key names colliding with its methods"
132
- fail ArgumentError, msg if methods.include? key.to_sym unless
133
- overwrite_methods
120
+ each_pair do |key, _|
121
+ fail ArgumentError, "key #{key} of #dot!-ted hash is not convertible " +
122
+ "to a symbol" unless key.respond_to? :to_sym
123
+ fail ArgumentError, "#dot!-ted hash must not have keys colliding with " +
124
+ "its methods" if methods.include? key.to_sym unless overwrite_methods
134
125
  define_singleton_method key.to_sym do self[key] end
135
- define_singleton_method "#{key}=".to_sym do |value| self[key] = value end
126
+ define_singleton_method "#{key}=".to_sym do |val| self[key] = val end
136
127
  end
137
- return self
138
128
  end
139
129
 
140
130
  # Pretty-prints the hash consisting of names as keys, and numeric values.
141
131
  # Takes 2 named arguments: +:gap+ and +:precision+.
142
132
  #
143
133
  def pretty_print_numeric_values gap: 0, precision: 2
144
- key_strings = keys.map &:to_s
134
+ lmax = keys.map( &:to_s ).map( &:size ).max
145
135
  value_strings = values.map { |n| "%.#{precision}f" % n rescue "%s" % n }
146
- lmax, rmax = key_strings.map( &:size ).max, value_strings.map( &:size ).max
136
+ rmax = value_strings.map( &:size ).max
147
137
  lgap = gap / 2
148
138
  rgap = gap - lgap
149
- key_strings.zip( value_strings ).map do |kς, vς|
150
- "%- #{lmax+lgap+1}s%#{rmax+rgap+1}.#{precision}f" % [ kς, ]
151
- end.each { |line| puts line }
152
- return nil
139
+ line = "%- #{lmax+lgap+1}s%#{rmax+rgap+1}.#{precision}f"
140
+ puts keys.zip( values ).map &line.method( :% )
153
141
  end
154
142
  end
155
-
@@ -1,2 +1,2 @@
1
- require 'y_support'
2
- require 'y_support/core_ext/hash/misc'
1
+ require 'y_support' unless defined? YSupport
2
+ require File.dirname( __FILE__ ) + '/hash/misc'
@@ -1,5 +1,30 @@
1
- #encoding: utf-8
1
+ class Module
2
+ # Sets a constant to a value if this has not been previously defined.
3
+ #
4
+ def const_set_if_not_defined( const, value )
5
+ const_set( const, value ) unless const_defined? const
6
+ end
2
7
 
8
+ # Redefines a constant without warning.
9
+ #
10
+ def const_reset!( const, value )
11
+ send :remove_const, const if const_defined? const
12
+ const_set( const, value )
13
+ end
14
+
15
+ # Defines a set of methods by applying the block on the return value of
16
+ # another set of methods. Accepts a hash of pairs { mapped_method_symbol =>
17
+ # original_method_symbol } and a block which to chain to the original
18
+ # method result.
19
+ #
20
+ def chain **hash, &block
21
+ hash.each_pair { |mapped_method_symbol, original_method_symbol|
22
+ define_method mapped_method_symbol do |*args, &b|
23
+ block.( send original_method_symbol, *args, &b )
24
+ end
25
+ }
26
+ end
27
+ end
3
28
  class Module
4
29
  # Sets a constant to a value if this has not been previously defined.
5
30
  #
@@ -13,4 +38,17 @@ class Module
13
38
  send :remove_const, const if const_defined? const
14
39
  const_set( const, value )
15
40
  end
41
+
42
+ # Defines a set of methods by applying the block on the return value of
43
+ # another set of methods. Accepts a hash of pairs { mapped_method_symbol =>
44
+ # original_method_symbol } and a block which to chain to the original
45
+ # method result.
46
+ #
47
+ def chain **hash, &block
48
+ hash.each_pair { |mapped_method_symbol, original_method_symbol|
49
+ define_method mapped_method_symbol do |*args, &b|
50
+ block.( send original_method_symbol, *args, &b )
51
+ end
52
+ }
53
+ end
16
54
  end
@@ -1,2 +1,2 @@
1
- require 'y_support'
2
- require 'y_support/core_ext/module/misc'
1
+ require 'y_support' unless defined? YSupport
2
+ require File.dirname( __FILE__ ) + '/module/misc'
@@ -1,5 +1,3 @@
1
- #encoding: utf-8
2
-
3
1
  class << Integer
4
2
  def zero; 0 end
5
3
  end
@@ -1,2 +1,2 @@
1
- require 'y_support'
2
- require 'y_support/core_ext/numeric/misc'
1
+ require 'y_support' unless defined? YSupport
2
+ require File.dirname( __FILE__ ) + '/numeric/misc'
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  class Object
4
2
  # Constructs the string "#{self.class}:#{self}". Useful for inspection.
5
3
  #
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'y_support/core_ext/class'
3
+ require File.dirname( __FILE__ ) + '/../class'
4
4
 
5
5
  class Object
6
6
  # Assigns prescribed atrributes to the object and makes them accessible with
@@ -14,38 +14,53 @@ class Object
14
14
  }
15
15
  end
16
16
 
17
- # Assigns prescribed atrributes to the object and makes them accessible with
18
- # getter (reader) methods. Shadows / overwrites existing methods.
17
+ # Like +#set_attr_with_readers+, but it overloads existing methods, if present.
18
+ # Whereas +#set_attr_with_readers+ guards against the presence of methods with
19
+ # the same name, +#set_attr_with_reader!+ overloads them in the following way:
20
+ #
21
+ # * Colliding instance method defined in the singleton class of the receiver
22
+ # is overwritten (redefined).
23
+ # * Colliding instance methods defined on the receiver's class ancestors are
24
+ # overloaded (partially shadowed). If the method message is sent without
25
+ # arguments or block, the reader activates and returns the corresponding
26
+ # instance variable regardless of what the behavior of the shadowed method
27
+ # might have been. However, if the method message is sent with arguments
28
+ # or block, the original method is invoked (via +super+) and its result
29
+ # returned.
19
30
  #
20
31
  def set_attr_with_readers! hash
21
32
  hash.each_pair { |symbol, value|
22
33
  instance_variable_set "@#{symbol}", value
23
- singleton_class.class_exec { attr_reader symbol }
34
+ singleton_class.class_exec do
35
+ define_method symbol do |*args, &block|
36
+ return instance_variable_get "@#{symbol}" if args.empty? && block.nil?
37
+ super *args, &block
38
+ end
39
+ end
24
40
  }
25
41
  end
26
42
 
27
43
  # Constructs parametrized subclasses of the supplied classes and makes them
28
- # available under specified getters. Expects a hash of pairs { reader_symbol:
29
- # class }, and a hash of parameters, with which the class(es) is (are)
30
- # parametrized. Raises NameError should any of the getters shadow / overwrite
31
- # existing methods.
44
+ # available under specified getters. Expects a hash of pairs { symbol: class },
45
+ # and a hash of parameters with which to parametrize the class(es). Guards
46
+ # against collisions in the subclass getter symbols, rasing NameError should
47
+ # these shadow or overwrite existing methods.
32
48
  #
33
- def param_class hash, with: (fail ArgumentError, "No parameters!")
49
+ def param_class( hash, with: {} )
34
50
  hash.each { |ß, ç|
35
- sub = ç.parametrize with
51
+ sub = ç.parametrize( with )
36
52
  set_attr_with_readers( ß => sub )
37
53
  }
38
54
  return nil
39
55
  end
40
56
 
41
- # Constructs parametrized subclasses of the supplied classes and makes them
42
- # available under specified getters. Expects a hash of pairs { reader_symbol:
43
- # class }, and a hash of parameters, with which the class(es) is (are)
44
- # parametrized. Shadows / overwrites existing methods.
57
+ # Like +#param_class+, but it shadows or overwrites existing methods colliding
58
+ # with the getters of the parametrized classes. See +#set_attr_with_readers!"
59
+ # for full explanation of the shadowing / overwriting behavior.
45
60
  #
46
- def param_class! hash, with: (fail ArgumentError, "No parameters!")
61
+ def param_class!( hash, with: {} )
47
62
  hash.each { |ß, ç|
48
- sub = ç.parametrize with
63
+ sub = ç.parametrize( with )
49
64
  set_attr_with_readers!( ß => sub )
50
65
  }
51
66
  return nil
@@ -1,3 +1,3 @@
1
- require 'y_support'
2
- require 'y_support/core_ext/object/misc'
3
- require 'y_support/core_ext/object/inspection'
1
+ require 'y_support' unless defined? YSupport
2
+ require File.dirname( __FILE__ ) + '/object/misc'
3
+ require File.dirname( __FILE__ ) + '/object/inspection'
@@ -1,4 +1,4 @@
1
- #encoding: utf-8
1
+ # encoding: utf-8
2
2
 
3
3
  require 'active_support/core_ext/object/blank'
4
4
 
@@ -32,7 +32,7 @@ class String
32
32
  .gsub("\n", "")
33
33
  .strip
34
34
  end
35
-
35
+
36
36
  # Joins a paragraph of possibly indented, newline separated lines into a
37
37
  # single contiguous string.
38
38
  #
@@ -43,19 +43,19 @@ class String
43
43
  .delete_if( &:blank? ) # delete blank lines
44
44
  .join " " # and join with whitspace
45
45
  end
46
-
46
+
47
47
  # If the string is empty, it gets replace with the string given as argument.
48
48
  #
49
49
  def default! default_string
50
50
  strip.empty? ? clear << default_string.to_s : self
51
51
  end
52
-
52
+
53
53
  # As it says – replaces spaces with underscores.
54
54
  #
55
55
  def underscore_spaces
56
56
  gsub ' ', '_'
57
57
  end
58
-
58
+
59
59
  # Converts a string into a standard symbol. While Symbol class objects can
60
60
  # be created from any string, it is good practice to keep symbols free of
61
61
  # whitespaces and weird characters, so that the are typed easily, usable as
@@ -70,7 +70,7 @@ class String
70
70
  .squeeze(" ")
71
71
  .underscore_spaces
72
72
  end
73
-
73
+
74
74
  # Applies #standardize to the receiver and converts the result to a symbol.
75
75
  #
76
76
  def to_standardized_sym
@@ -78,7 +78,7 @@ class String
78
78
  .to_sym
79
79
  end
80
80
 
81
- # Capitalizes a string and append an exclamation mark. Also allows optional
81
+ # Capitalizes a string and appends an exclamation mark. Also allows optional
82
82
  # argument for string interpolation. Handy for constructing error messages.
83
83
  #
84
84
  def X! arg=nil
@@ -1,2 +1,2 @@
1
- require 'y_support'
2
- require 'y_support/core_ext/string/misc'
1
+ require 'y_support' unless defined? YSupport
2
+ require File.dirname( __FILE__ ) + '/string/misc'
@@ -1,6 +1,5 @@
1
- # -*- coding: utf-8 -*-
2
1
  class Symbol
3
- # This method applies String#default! method to the receiver converted to
2
+ # This method applies +String#default!+ method to the receiver converted to
4
3
  # a string. Of course, symbols are immutable, so in spite of the exclamation
5
4
  # mark in the method name, a new symbol (supplied as argument) is returned,
6
5
  # if the original one is considered "defaulted" (otherwise, original symbol
@@ -10,7 +9,7 @@ class Symbol
10
9
  to_s.default!( default_symbol ).to_sym
11
10
  end
12
11
 
13
- # Applies String#to_standardized_sym method to the recevier converted to a
12
+ # Applies +String#to_standardized_sym+ method to the recevier converted to a
14
13
  # string.
15
14
  #
16
15
  def to_standardized_sym
@@ -1,2 +1,2 @@
1
- require 'y_support'
2
- require 'y_support/core_ext/symbol/misc'
1
+ require 'y_support' unless defined? YSupport
2
+ require File.dirname( __FILE__ ) + '/symbol/misc'
@@ -1,5 +1,3 @@
1
- #encoding: utf-8
2
-
3
1
  Dir["#{File.dirname( __FILE__ )}/core_ext/*.rb"].sort.each do |path|
4
2
  require "y_support/core_ext/#{File.basename( path, '.rb' )}"
5
3
  end
@@ -1,4 +1,4 @@
1
- #encoding: utf-8
1
+ # encoding: utf-8
2
2
 
3
3
  require 'y_support'
4
4
 
data/lib/y_support/kde.rb CHANGED
@@ -11,3 +11,4 @@ module YSupport::KDE
11
11
  end
12
12
  end
13
13
  end # module YSupport::KDE
14
+
@@ -1,13 +1,14 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  class Array
4
- # Maps an array to an array of the element names, obtained by applying +#name+
5
- # method to them. Takes one optional argument, which regulates its behavior
6
- # regarding unnamed objects. If set to _nil_ (default) unnamed objects will
7
- # be mapped to _nil_ (default behavior of the +#name+ method). If set to
8
- # _true_, unnamed objects will be mapped to themselves. If set to _false_,
9
- # unnamed object will not be mapped at all -- the returned array will contain
10
- # only the names of the named objects.
4
+ # Maps an array of some objects into an array of their names, obtained by
5
+ # applying +#full_name+ method to them. Takes one optional argument, which
6
+ # regulates its behavior regarding unnamed objects. If set to _nil_ (default),
7
+ # unnamed
8
+ # objects will be mapped to _nil_ (default behavior of the +#name+ method).
9
+ # If set to _true_, unnamed objects will be mapped to themselves. If set to
10
+ # _false_, unnamed objects will not be mapped at all -- the returned array will
11
+ # contain only the names of the named objects.
11
12
  #
12
13
  def names option=nil
13
14
  return map &:name if option.nil? # unnamed --> nil
@@ -15,4 +16,23 @@ class Array
15
16
  return map( &:name ).compact if option == false # unnamed squeezed out
16
17
  fail ArgumentError, "Unknown option: #{option}"
17
18
  end
19
+ # FIXME: The remaining thing to do to achieve compatibility with Ruby's #name
20
+ # is to put "full_name" in the body, and "name" in the alias...
21
+ alias full_names names
22
+
23
+ # Maps an array to an array of the element names, obtained by applying
24
+ # +#_name_+ method to them. Takes one optional argument, which regulates its
25
+ # behavior regarding unnamed objects. If set to _nil_ (default) unnamed
26
+ # objects will be mapped to _nil_ (default behavior of +#_name_+ method). If
27
+ # set to _true_, unnamed objects will be mapped to themselves. If set to
28
+ # _false_, unnamed objects will not be mapped at all -- the returned array
29
+ # will contain only the names of the named objects.
30
+ #
31
+ def _names_ option=nil
32
+ return map &:_name_ if option.nil? # unnamed --> nil
33
+ return map { |e| e.name || e } if option == true # unnamed --> instance
34
+ return map( &:_name_ ).compact if option == false # unnamed squeezed out
35
+ fail ArgumentError, "Unknown option: #{option}"
36
+ end
37
+ alias ɴs _names_
18
38
  end