nrser 0.3.9 → 0.3.10

Sign up to get free protection for your applications and to get access to all the features.
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
+