nrser 0.3.9 → 0.3.10

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 (141) hide show
  1. checksums.yaml +4 -4
  2. data/lib/nrser/char/alpha_numeric_sub.rb +9 -19
  3. data/lib/nrser/char/special.rb +5 -5
  4. data/lib/nrser/core_ext/array.rb +36 -13
  5. data/lib/nrser/core_ext/enumerable.rb +1 -0
  6. data/lib/nrser/core_ext/enumerable/find_map.rb +1 -1
  7. data/lib/nrser/core_ext/hash/bury.rb +3 -0
  8. data/lib/nrser/core_ext/hash/extract_values_at.rb +2 -2
  9. data/lib/nrser/core_ext/method/full_name.rb +1 -1
  10. data/lib/nrser/core_ext/module/method_objects.rb +1 -1
  11. data/lib/nrser/core_ext/module/source_locations.rb +27 -15
  12. data/lib/nrser/core_ext/object/lazy_var.rb +1 -1
  13. data/lib/nrser/core_ext/pathname.rb +67 -12
  14. data/lib/nrser/core_ext/pathname/subpath.rb +86 -0
  15. data/lib/nrser/core_ext/string.rb +28 -1
  16. data/lib/nrser/core_ext/symbol.rb +11 -12
  17. data/lib/nrser/errors/README.md +154 -0
  18. data/lib/nrser/errors/attr_error.rb +146 -53
  19. data/lib/nrser/errors/count_error.rb +61 -12
  20. data/lib/nrser/errors/nicer_error.rb +42 -71
  21. data/lib/nrser/errors/value_error.rb +53 -58
  22. data/lib/nrser/functions.rb +0 -2
  23. data/lib/nrser/functions/enumerable.rb +5 -17
  24. data/lib/nrser/functions/enumerable/associate.rb +14 -5
  25. data/lib/nrser/functions/enumerable/find_all_map.rb +1 -1
  26. data/lib/nrser/functions/enumerable/include_slice/array_include_slice.rb +1 -1
  27. data/lib/nrser/functions/hash/bury.rb +2 -12
  28. data/lib/nrser/functions/merge_by.rb +2 -2
  29. data/lib/nrser/functions/module/method_objects.rb +2 -2
  30. data/lib/nrser/functions/path.rb +185 -165
  31. data/lib/nrser/functions/path/normalized.rb +84 -0
  32. data/lib/nrser/functions/string.rb +4 -4
  33. data/lib/nrser/functions/text/README.md +4 -0
  34. data/lib/nrser/functions/text/format.rb +53 -0
  35. data/lib/nrser/functions/text/indentation.rb +6 -6
  36. data/lib/nrser/functions/text/word_wrap.rb +2 -2
  37. data/lib/nrser/functions/tree/map_leaves.rb +3 -3
  38. data/lib/nrser/functions/tree/map_tree.rb +2 -2
  39. data/lib/nrser/functions/tree/transform.rb +1 -18
  40. data/lib/nrser/gem_ext/README.md +4 -0
  41. data/lib/nrser/labs/README.md +8 -0
  42. data/lib/nrser/labs/config.rb +163 -0
  43. data/lib/nrser/labs/i8.rb +49 -159
  44. data/lib/nrser/labs/i8/struct.rb +167 -0
  45. data/lib/nrser/labs/i8/struct/hash.rb +140 -0
  46. data/lib/nrser/labs/i8/struct/vector.rb +149 -0
  47. data/lib/nrser/labs/i8/surjection.rb +211 -0
  48. data/lib/nrser/labs/lots/consumer.rb +19 -0
  49. data/lib/nrser/labs/lots/parser.rb +21 -1
  50. data/lib/nrser/labs/stash.rb +4 -4
  51. data/lib/nrser/log.rb +25 -21
  52. data/lib/nrser/log/appender/sync.rb +15 -11
  53. data/lib/nrser/log/formatters/color.rb +0 -3
  54. data/lib/nrser/log/formatters/mixin.rb +4 -4
  55. data/lib/nrser/log/logger.rb +54 -6
  56. data/lib/nrser/log/mixin.rb +2 -1
  57. data/lib/nrser/log/plugin.rb +6 -6
  58. data/lib/nrser/log/types.rb +46 -29
  59. data/lib/nrser/mean_streak.rb +0 -8
  60. data/lib/nrser/mean_streak/document.rb +1 -4
  61. data/lib/nrser/message.rb +3 -3
  62. data/lib/nrser/meta/README.md +4 -0
  63. data/lib/nrser/meta/lazy_attr.rb +2 -2
  64. data/lib/nrser/meta/source/location.rb +1 -1
  65. data/lib/nrser/props.rb +34 -3
  66. data/lib/nrser/props/class_methods.rb +2 -1
  67. data/lib/nrser/props/instance_methods.rb +9 -9
  68. data/lib/nrser/props/metadata.rb +4 -12
  69. data/lib/nrser/props/mutable/stash.rb +5 -2
  70. data/lib/nrser/props/prop.rb +10 -19
  71. data/lib/nrser/rspex.rb +1 -20
  72. data/lib/nrser/rspex/example_group/describe_attribute.rb +3 -0
  73. data/lib/nrser/rspex/example_group/describe_called_with.rb +9 -4
  74. data/lib/nrser/rspex/example_group/describe_case.rb +1 -0
  75. data/lib/nrser/rspex/example_group/describe_class.rb +2 -0
  76. data/lib/nrser/rspex/example_group/describe_group.rb +1 -1
  77. data/lib/nrser/rspex/example_group/describe_instance.rb +3 -1
  78. data/lib/nrser/rspex/example_group/describe_message.rb +1 -1
  79. data/lib/nrser/rspex/example_group/describe_method.rb +64 -30
  80. data/lib/nrser/rspex/example_group/describe_response_to.rb +1 -1
  81. data/lib/nrser/rspex/example_group/describe_section.rb +4 -1
  82. data/lib/nrser/rspex/example_group/describe_sent_to.rb +1 -1
  83. data/lib/nrser/rspex/example_group/describe_setup.rb +1 -0
  84. data/lib/nrser/rspex/example_group/describe_source_file.rb +1 -1
  85. data/lib/nrser/rspex/example_group/describe_spec_file.rb +4 -2
  86. data/lib/nrser/rspex/example_group/describe_when.rb +2 -1
  87. data/lib/nrser/rspex/example_group/describe_x.rb +5 -5
  88. data/lib/nrser/rspex/format.rb +0 -15
  89. data/lib/nrser/sugar/method_missing_forwarder.rb +3 -3
  90. data/lib/nrser/sys/env/path.rb +2 -28
  91. data/lib/nrser/types.rb +63 -12
  92. data/lib/nrser/types/README.md +76 -0
  93. data/lib/nrser/types/arrays.rb +192 -137
  94. data/lib/nrser/types/attributes.rb +269 -0
  95. data/lib/nrser/types/booleans.rb +134 -83
  96. data/lib/nrser/types/bounded.rb +110 -47
  97. data/lib/nrser/types/collections.rb +119 -0
  98. data/lib/nrser/types/combinators.rb +283 -196
  99. data/lib/nrser/types/doc/display_table.md +66 -0
  100. data/lib/nrser/types/eqiuvalent.rb +91 -0
  101. data/lib/nrser/types/errors/check_error.rb +5 -11
  102. data/lib/nrser/types/errors/from_string_error.rb +3 -3
  103. data/lib/nrser/types/factory.rb +287 -20
  104. data/lib/nrser/types/hashes.rb +227 -179
  105. data/lib/nrser/types/in.rb +73 -36
  106. data/lib/nrser/types/is.rb +67 -60
  107. data/lib/nrser/types/is_a.rb +141 -84
  108. data/lib/nrser/types/labels.rb +45 -16
  109. data/lib/nrser/types/maybe.rb +6 -3
  110. data/lib/nrser/types/nil.rb +64 -27
  111. data/lib/nrser/types/not.rb +92 -34
  112. data/lib/nrser/types/numbers.rb +224 -169
  113. data/lib/nrser/types/pairs.rb +113 -89
  114. data/lib/nrser/types/paths.rb +250 -137
  115. data/lib/nrser/types/responds.rb +167 -89
  116. data/lib/nrser/types/selector.rb +234 -0
  117. data/lib/nrser/types/shape.rb +136 -65
  118. data/lib/nrser/types/strings.rb +189 -63
  119. data/lib/nrser/types/symbols.rb +83 -33
  120. data/lib/nrser/types/top.rb +89 -0
  121. data/lib/nrser/types/tuples.rb +134 -98
  122. data/lib/nrser/types/type.rb +617 -505
  123. data/lib/nrser/types/when.rb +123 -98
  124. data/lib/nrser/types/where.rb +182 -91
  125. data/lib/nrser/version.rb +1 -1
  126. data/spec/lib/nrser/core_ext/pathname/subpath_spec.rb +22 -0
  127. data/spec/lib/nrser/errors/attr_error_spec.rb +68 -0
  128. data/spec/lib/nrser/errors/count_error_spec.rb +69 -0
  129. data/spec/lib/nrser/functions/path/normalize_path_spec.rb +35 -0
  130. data/spec/lib/nrser/functions/tree/map_tree_spec.rb +74 -96
  131. data/spec/lib/nrser/functions/tree/transform_spec.rb +11 -11
  132. data/spec/lib/nrser/labs/config_spec.rb +22 -0
  133. data/spec/lib/nrser/labs/i8/struct_spec.rb +39 -0
  134. data/spec/lib/nrser/types/display_spec.rb +50 -0
  135. data/spec/lib/nrser/types/paths_spec.rb +16 -10
  136. data/spec/lib/nrser/types/selector_spec.rb +125 -0
  137. data/spec/spec_helper.rb +4 -5
  138. metadata +105 -22
  139. data/lib/nrser/types/any.rb +0 -41
  140. data/lib/nrser/types/attrs.rb +0 -213
  141. data/lib/nrser/types/trees.rb +0 -42
@@ -1,100 +1,178 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
1
4
  require 'nrser/message'
2
5
  require_relative './booleans'
3
6
 
4
- module NRSER::Types
7
+
8
+ # Namespace
9
+ # ========================================================================
10
+
11
+ module NRSER
12
+ module Types
13
+
14
+
15
+ # Definitions
16
+ # ========================================================================
17
+
18
+ # This {Type} is used to test how the values in question respond to specific
19
+ # messages (method calls).
20
+ #
21
+ # {Respond} instances hold a {#message} and {#response} type. Instances
22
+ # that respond when sent the message with a value that satisfies the
23
+ # response type are members.
24
+ #
25
+ # @example Type whose members have non-empty string names.
26
+ # type = Types:Respond.new \
27
+ # to: :name,
28
+ # with: Types.non_empty_str
29
+ #
30
+ class Respond < Type
31
+
32
+ # Attributes
33
+ # ======================================================================
5
34
 
6
- # Type holding an {NRSER::Message} and response type. Satisfied by objects
7
- # that respond with a value that satisfies the respond type when sent the
8
- # message.
35
+ # Message that will be sent to tested values.
9
36
  #
10
- class Respond < NRSER::Types::Type
11
-
12
- # Attributes
13
- # ======================================================================
14
-
15
- # Message that will be sent to tested values.
16
- #
17
- # @return [NRSER::Message]
18
- #
19
- attr_reader :message
20
-
21
-
22
- # Type tested values must respond with when sent the message.
23
- #
24
- # @return [NRSER::Types::Type]
25
- #
26
- attr_reader :response
27
-
28
-
29
-
30
- # TODO document `publicly` attribute.
31
- #
32
- # @return [Boolean]
33
- #
34
- attr_reader :publicly
35
-
36
-
37
-
38
- # Constructor
39
- # ======================================================================
40
-
41
- # Instantiate a new `Respond`.
42
- def initialize to:,
43
- with:,
44
- publicly: true,
45
- **options
46
- @message = NRSER::Message.from *to
47
- @publicly = publicly
48
- @response = NRSER::Types.make with
49
-
50
- super **options
51
- end # #initialize
52
-
53
-
54
- # Instance Methods
55
- # ======================================================================
37
+ # @return [NRSER::Message]
38
+ #
39
+ attr_reader :message
40
+
41
+
42
+ # Type tested values must respond with when sent the message.
43
+ #
44
+ # @return [Type]
45
+ #
46
+ attr_reader :response
47
+
48
+
49
+ # Controls whether the {#message} will be sent using `#public_send` (the
50
+ # default) or `#send` - which has access to private and protected
51
+ # methods.
52
+ #
53
+ # @return [Boolean]
54
+ #
55
+ attr_reader :publicly
56
+
57
+
58
+ # Constructor
59
+ # ======================================================================
60
+
61
+ # Instantiate a new instance.
62
+ #
63
+ # See construction example in the class header: {Respond}.
64
+ #
65
+ # @param [String | Symbol | Array] to
66
+ # Fed in to {NRSER::Message.from} to create the {#message}.
67
+ #
68
+ # Must be a lone string or symbol representing the method name to call,
69
+ # or an Array with the string or symbol methods name in the first entry
70
+ # (and whatever other parameters can follow it).
71
+ #
72
+ # @param [Type | Object] with
73
+ # The type members must respond with. If `with:` is not a {Type} it will
74
+ # be made into on via {Types.make}.
75
+ #
76
+ # @param [Boolean] publicly
77
+ # Chooses between using `#public_send` and `#send` to send the {#message}.
78
+ #
79
+ # @param [Hash] options
80
+ # Additional options that will be passed up to {Type#initialize}.
81
+ #
82
+ def initialize to:,
83
+ with:,
84
+ publicly: true,
85
+ **options
86
+ @message = NRSER::Message.from *to
87
+ @publicly = publicly
88
+ @response = NRSER::Types.make with
89
+
90
+ super **options
91
+ end # #initialize
92
+
93
+
94
+ # Instance Methods
95
+ # ======================================================================
96
+
97
+ # See {Type#explain}.
98
+ #
99
+ # @param (see Type#explain)
100
+ # @return (see Type#explain)
101
+ # @raise (see Type#explain)
102
+ #
103
+ def explain
104
+ args_str = message.args.map( &:inspect ).join ', '
56
105
 
57
- # See {NRSER::Types::Type#explain}.
58
- #
59
- # @param (see NRSER::Types::Type#explain)
60
- # @return (see NRSER::Types::Type#explain)
61
- # @raise (see NRSER::Types::Type#explain)
62
- #
63
- def explain
64
- args_str = message.args.map( &:inspect ).join ', '
65
-
66
- if message.block
67
- args_str += ', ' + message.block.to_s
68
- end
69
-
70
- "##{ message.symbol }(#{ args_str })#{ RESPONDS_WITH }#{ response.explain }"
106
+ if message.block
107
+ args_str += ', ' + message.block.to_s
71
108
  end
72
109
 
73
-
74
- # Test value for membership.
75
- #
76
- # @param (see NRSER::Types::Type#test?)
77
- # @return (see NRSER::Types::Type#test?)
78
- # @raise (see NRSER::Types::Type#test?)
79
- #
80
- def test? value
81
- response.test message.send_to( value, publicly: publicly )
82
- end # #test
83
-
84
- end # class Responds
110
+ "##{ message.symbol }(#{ args_str })#{ RESPONDS_WITH }#{ response.explain }"
111
+ end
85
112
 
86
-
87
- def_factory(
88
- :respond,
89
- ) do |*args|
90
- Respond.new *args
91
- end # #responds
92
113
 
114
+ # Test value for membership.
115
+ #
116
+ # @param (see Type#test?)
117
+ # @return (see Type#test?)
118
+ # @raise (see Type#test?)
119
+ #
120
+ def test? value
121
+ response.test message.send_to( value, publicly: publicly )
122
+ end # #test
93
123
 
94
- def_factory(
95
- :respond_to
96
- ) do |method_name, **options|
97
- respond to: [:respond_to?, method_name], with: NRSER::Types.true
98
- end # #respond_to
99
-
100
- end # module NRSER::Types
124
+ end # class Responds
125
+
126
+
127
+ # Factories
128
+ # ----------------------------------------------------------------------------
129
+
130
+ # @!group Method Response Type Factories
131
+ # ----------------------------------------------------------------------------
132
+
133
+ #@!method self.Respond to:, with:, publicly: true, **options
134
+ # Create a {Respond} type.
135
+ #
136
+ # @param (see Respond#initialize)
137
+ #
138
+ # @return [Respond]
139
+ #
140
+ def_type :Respond,
141
+ default_name: false,
142
+ parameterize: [ :to, :with, :publicly ],
143
+ &->( to:, with:, publicly: true, **options ) do
144
+ Respond.new to: to, with: with, publicly: publicly, **options
145
+ end # .Respond
146
+
147
+
148
+ #@!method self.RespondTo method_name, **options
149
+ # Gets a {Respond} that admits values that `#respond_to?` a `method_name`.
150
+ #
151
+ # @param [Symbol | String] method_name
152
+ # The name of the method that type members must `#respond_to?`.
153
+ #
154
+ # @param [Hash] options
155
+ # Passed to {Type#initialize}.
156
+ #
157
+ # @return [Respond]
158
+ #
159
+ def_type :RespondTo,
160
+ default_name: ->( method_name, **options ) {
161
+ "RespondTo<#{ method_name }>"
162
+ },
163
+ parameterize: :method_name,
164
+ # TODO I'm not sure how this worked before, but defining `.respond_to?`
165
+ # def fucks things up...
166
+ # maybe: false,
167
+ &->( method_name, **options ) do
168
+ respond to: [:respond_to?, method_name], with: self.True
169
+ end # .RespondTo
170
+
171
+ # @!endgroup Method Response Type Factories # ********************************
172
+
173
+
174
+ # /Namespace
175
+ # ========================================================================
176
+
177
+ end # module Types
178
+ end # module NRSER
@@ -0,0 +1,234 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Project / Package
8
+ # -----------------------------------------------------------------------
9
+
10
+ require_relative './combinators'
11
+ require_relative './when'
12
+ require_relative './shape'
13
+ require_relative './collections'
14
+
15
+
16
+ # Namespace
17
+ # =======================================================================
18
+
19
+ module NRSER
20
+ module Types
21
+
22
+
23
+ # Definitions
24
+ # =======================================================================
25
+
26
+ # @!group Selector Type Factories
27
+ # ----------------------------------------------------------------------------
28
+
29
+ #@!method self.Selector pairs, **options
30
+ # Factory to create {Shape} type instances that function as MongoDB-esque
31
+ # document query against lists of Ruby objects using the standard
32
+ # {Enumerable#select} and related methods.
33
+ #
34
+ # @example
35
+ # # Some sample data
36
+ #
37
+ # people = [
38
+ # {name: "Neil", fav_color: "blue", likes: ["cat", "scotch", "computer"]},
39
+ # {name: "Mica", fav_color: "red", like: ["cat", "beer", "dance"]},
40
+ # ]
41
+ #
42
+ # # Simple value matching
43
+ #
44
+ # people.select( &t[ name: "Neil" ] ).map &[:name]
45
+ # # => [ "Neil" ]
46
+ #
47
+ # # NOTE 1. We're using the `t -> NRSER::Types` short-hand alias, as
48
+ # # provided by `using NRSER::Types` refinement.
49
+ # #
50
+ # # 2. {NRSER::Types.[]} is a short-hand alias for
51
+ # # {NRSER::Types.Selector}.
52
+ # #
53
+ # # 3. The `&[:name]` uses NRSER's {Array#to_proc} core extension.
54
+ # # It's equivalent to `{ |h| h[:name] }`.
55
+ # #
56
+ #
57
+ # people.select( &t[ fav_color: "red" ] ).map &[:name]
58
+ # # => [ "Mica" ]
59
+ #
60
+ # # Fields that are {NRSER::Types.Bag} (think Array and Set but not Hash)
61
+ # # match against *any* of the values
62
+ #
63
+ # people.select( &t[ likes: "cat" ] ).map &[:name]
64
+ # # => [ "Neil", "Mica" ]
65
+ #
66
+ # # Literal arrays are treated like literals, however, and must match
67
+ # # *exactly*
68
+ #
69
+ # people.select( &t[ likes: [ "cat", "computer" ] ] ).map &[:name]
70
+ # # => []
71
+ #
72
+ # people.select( &t[ likes: [ "cat", "computer", "scotch" ] ] ).map &[:name]
73
+ # # => []
74
+ #
75
+ # people.select( &t[ likes: [ "cat", "scotch", "computer" ] ] ).map &[:name]
76
+ # # => ["Neil"]
77
+ #
78
+ # # To match against *any* of a list of terms you can construct a
79
+ # # {NRSER::Types.HasAny}
80
+ #
81
+ # people.select( &t[ likes: t.HasAny( "computer", "dance" ) ]).map &[:name]
82
+ # # => ["Neil", "Mica"]
83
+ #
84
+ # # The {NRSER::Types.Has} and {.HasAny} do create types for the terms and
85
+ # # do a `#find` against them, so you can use any of the {NRSER::Types}
86
+ # # system in there.
87
+ # #
88
+ # # Here is using a {RegExp} (which {NRSER::Types.make} wraps in a
89
+ # # {NRSER::Types::When}):
90
+ #
91
+ # people.select( &t[ fav_color: /\A[bg]/ ] ).map &[:name]
92
+ #
93
+ # Selectors are in the very early and experimental stage, but it's something
94
+ # I've been thinking about for a while now that suddenly just sort-of fell
95
+ # into place.
96
+ #
97
+ # Eventually I want to be able to use these same selectors on SQL, MongoDB,
98
+ # ActiveRecord, etc.
99
+ #
100
+ # @see https://docs.mongodb.com/manual/tutorial/query-documents/
101
+ # MongoDB Query Tutorial
102
+ # @see https://docs.mongodb.com/manual/reference/operator/query/
103
+ # MongoDB Query and Projection Operators
104
+ #
105
+ # @status
106
+ # Experimental
107
+ #
108
+ # @param [Hash<Object, TYPE>] pairs
109
+ # Keys will be the keys in the resulting {.Shape} type.
110
+ #
111
+ # Values that are {Type} instances are used as is for the {Shape} value
112
+ # type. Everything else gets run through
113
+ #
114
+ # @param [Hash] options
115
+ # Passed to {Type#initialize}.
116
+ #
117
+ # @return [Shape]
118
+ #
119
+ def_type :Selector,
120
+ aliases: [ :query, :[] ],
121
+ # I don't think we need the `?` methods for Selector?
122
+ maybe: false,
123
+ parameterize: :pairs,
124
+ &->( pairs, **options ) do
125
+ shape \
126
+ pairs.transform_values { |value|
127
+ if value.is_a?( Type )
128
+ value
129
+ else
130
+ value_type = self.When value
131
+ self.or(
132
+ value_type,
133
+ (bag & has( value_type )),
134
+ name: "{#{ value.inspect }}"
135
+ )
136
+ end
137
+ },
138
+ **options
139
+ end # .Selector
140
+
141
+ # @!endgroup Selector Type Factories # ***************************************
142
+
143
+
144
+ # @!group Find Type Factories
145
+ # ----------------------------------------------------------------------------
146
+ #
147
+
148
+ # @method self.Has member, **options
149
+ #
150
+ # Type that tests value for membership in a group object via that object's
151
+ # `#include?` method.
152
+ #
153
+ # @todo
154
+ # The "find" factories got introduced to support {.Selector}, and need
155
+ # improvement. They're really just stop gaps at the moment, and have
156
+ # already been considerably changed a few times.
157
+ #
158
+ # I want to eventually make selectors able to output SQL, MongoDB, etc.
159
+ # queries, which will require we get rid of the {.Where} usage...
160
+ #
161
+ # @status
162
+ # Experimental
163
+ #
164
+ # @param [Object] member
165
+ # The object that needs to be included for type satisfaction.
166
+ #
167
+ # @param [Hash] options
168
+ # Passed to {Type#initialize}.
169
+ #
170
+ # @return [Type]
171
+ #
172
+ def_type :Has,
173
+ parameterize: :member,
174
+ aliases: [ :has, :includes ],
175
+ &->( member, **options ) do
176
+ # Provide a some-what useful default name
177
+ options[:name] ||= "Has<#{ NRSER.smart_ellipsis member.inspect, 64 }>"
178
+
179
+ member_type = make member
180
+
181
+ where( **options ) { |value|
182
+ value.respond_to?( :find ) &&
183
+ # value.find { |entry| member_type === entry }
184
+ value.find( &member_type )
185
+ }
186
+ end # .Has
187
+
188
+
189
+ #@!method self.HasAny *members, **options
190
+ # Match values that have *any* of `members`.
191
+ #
192
+ # @todo
193
+ # The "find" factories got introduced to support {.Selector}, and need
194
+ # improvement. They're really just stop gaps at the moment, and have
195
+ # already been considerably changed a few times.
196
+ #
197
+ # I want to eventually make selectors able to output SQL, MongoDB, etc.
198
+ # queries, which will require we get rid of the {.Where} usage...
199
+ #
200
+ # @status
201
+ # Experimental
202
+ #
203
+ # @param [Array<TYPE>] members
204
+ # Resulting type will be satisfied by values in which it can `#find` any
205
+ # entry that any of `members` is satisfied by. `members` entries that are
206
+ # not {Type} instances will be made into them via {.make}.
207
+ #
208
+ # @param [Hash] options
209
+ # Passed to {Type#initialize}.
210
+ #
211
+ # @return [Type]
212
+ #
213
+ def_type :HasAny,
214
+ parameterize: :members,
215
+ aliases: [ :intersects ],
216
+ &->( *members, **options ) do
217
+ options[:name] ||= \
218
+ "HasAny<#{ NRSER.smart_ellipsis members.inspect, 64 }>"
219
+
220
+ member_types = members.map { |m| make m }
221
+
222
+ where( **options ) {
223
+ |group| member_types.any? { |member_type| group.find &member_type }
224
+ }
225
+ end # .HasAny
226
+
227
+ # @!endgroup Find Type Factories # *******************************************
228
+
229
+ # /Namespace
230
+ # =======================================================================
231
+
232
+ end # module Types
233
+ end # module NRSER
234
+