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,208 +1,256 @@
1
+ # encoding: UTF-8
2
+ # frozen_string_literal: true
3
+
4
+ # Requirements
5
+ # ========================================================================
6
+
7
+ # Project / Package
8
+ # ------------------------------------------------------------------------
9
+
1
10
  require_relative './type'
11
+
12
+
13
+ # Namespace
14
+ # ========================================================================
15
+
16
+ module NRSER
17
+ module Types
18
+
19
+
20
+ # Definitions
21
+ # ========================================================================
22
+
23
+ # A type who's members simply are {Hash} instances.
24
+ #
25
+ # Implements {#from_s} to provide JSON/YAML detection, as well as "simple"
26
+ # loading aimed at CLI option values.
27
+ #
28
+ # @note
29
+ # Construct {HashType} types using the {.Hash} factory.
30
+ #
31
+ class HashType < IsA
32
+
33
+ # Constructor
34
+ # ========================================================================
35
+
36
+ # Instantiate a new `HashType`.
37
+ def initialize **options
38
+ super ::Hash, **options
39
+ end # #initialize
2
40
 
3
- module NRSER::Types
4
41
 
5
- # A type who's members simply are {Hash} instances.
42
+ # Instance Methods
43
+ # ========================================================================
44
+
45
+ # In order to provide the same interface as {HashOfType}, this method
46
+ # always returns {NRSER::Types.any}.
6
47
  #
7
- # Implements {#from_s} to provide JSON/YAML detection, as well as "simple"
8
- # loading aimed at CLI option values.
48
+ # @return [NRSER::Types::Type]
9
49
  #
10
- class HashType < IsA
50
+ def keys; NRSER::Types.Top; end
11
51
 
12
- # Constructor
13
- # ========================================================================
14
-
15
- # Instantiate a new `HashType`.
16
- def initialize **options
17
- super ::Hash, **options
18
- end # #initialize
19
-
20
-
21
- # Instance Methods
22
- # ========================================================================
23
-
24
- # In order to provide the same interface as {HashOfType}, this method
25
- # always returns {NRSER::Types.any}.
26
- #
27
- # @return [NRSER::Types::Type]
28
- #
29
- def keys; NRSER::Types.any; end
30
-
31
-
32
- # In order to provide the same interface as {HashOfType}, this method
33
- # always returns {NRSER::Types.any}.
34
- #
35
- # @return [NRSER::Types::Type]
52
+
53
+ # In order to provide the same interface as {HashOfType}, this method
54
+ # always returns {NRSER::Types.any}.
55
+ #
56
+ # @return [NRSER::Types::Type]
57
+ #
58
+ def values; NRSER::Types.Top; end
59
+
60
+
61
+ def default_symbolic
62
+ "{#{ keys.symbolic }#{ ASSOC }#{ values.symbolic }}"
63
+ end
64
+
65
+
66
+ protected
67
+ # ========================================================================
68
+
69
+ # Hook to provide custom loading from strings, which will be called by
70
+ # {NRSER::Types::Type#from_s}, unless a `@from_s`
36
71
  #
37
- def values; NRSER::Types.any; end
38
-
39
-
40
- protected
41
- # ========================================================================
42
-
43
- # Hook to provide custom loading from strings, which will be called by
44
- # {NRSER::Types::Type#from_s}, unless a `@from_s`
45
- #
46
- def custom_from_s string
47
- # Does it looks like a JSON / inline-YAML object?
48
- if NRSER.looks_like_json_object? string
49
- # It does! Load it
50
- begin
51
- return YAML.load string
52
- rescue
53
- # pass - if we failed to load as JSON, it may just not be JSON, and
54
- # we can try the split approach below.
55
- end
72
+ def custom_from_s string
73
+ # Does it looks like a JSON / inline-YAML object?
74
+ if NRSER.looks_like_json_object? string
75
+ # It does! Load it
76
+ begin
77
+ return YAML.load string
78
+ rescue
79
+ # pass - if we failed to load as JSON, it may just not be JSON, and
80
+ # we can try the split approach below.
56
81
  end
57
-
58
- # Try parsing as a "simple string", aimed at CLI option values.
59
- from_simple_s string
60
82
  end
61
83
 
84
+ # Try parsing as a "simple string", aimed at CLI option values.
85
+ from_simple_s string
86
+ end
87
+
88
+
89
+ def from_simple_s string
90
+ hash = {}
62
91
 
63
- def from_simple_s string
64
- hash = {}
65
-
66
- pair_strs = string.split NRSER::Types::ArrayType::DEFAULT_SPLIT_WITH
92
+ pair_strs = string.split NRSER::Types::ArrayType::DEFAULT_SPLIT_WITH
93
+
94
+ pair_strs.each do |pair_str|
95
+ key_str, match, value_str = pair_str.rpartition /\:\s*/m
67
96
 
68
- pair_strs.each do |pair_str|
69
- key_str, match, value_str = pair_str.rpartition /\:\s*/m
70
-
71
- if match.empty?
72
- raise NRSER::Types::FromStringError.new(
73
- "Could not split pair string", pair_str,
74
- type: self,
75
- string: string,
76
- pair_str: pair_str,
77
- ) do
78
- <<~END
79
- Trying to parse a {Hash} out of a string using the "simple"
80
- approach, which splits
81
-
82
- 1. First by `,` (followed by any amount of whitespace)
83
- 2. Then by the last `:` in each of those splits (also followed)
84
- by any amount of whitespace)
85
- END
86
- end
87
- end
88
-
89
- key = if keys == NRSER::Types.any
90
- key_str
91
- else
92
- keys.from_s key_str
97
+ if match.empty?
98
+ raise NRSER::Types::FromStringError.new(
99
+ "Could not split pair string", pair_str,
100
+ type: self,
101
+ string: string,
102
+ pair_str: pair_str,
103
+ ) do
104
+ <<~END
105
+ Trying to parse a {Hash} out of a string using the "simple"
106
+ approach, which splits
107
+
108
+ 1. First by `,` (followed by any amount of whitespace)
109
+ 2. Then by the last `:` in each of those splits (also followed)
110
+ by any amount of whitespace)
111
+ END
93
112
  end
94
-
95
- value = if values == NRSER::Types.any
96
- value_str
97
- else
98
- values.from_s value_str
99
- end
100
-
101
- hash[key] = value
102
113
  end
103
114
 
104
- hash
105
- end # #from_simple_s
115
+ key = if keys == NRSER::Types.any
116
+ key_str
117
+ else
118
+ keys.from_s key_str
119
+ end
120
+
121
+ value = if values == NRSER::Types.any
122
+ value_str
123
+ else
124
+ values.from_s value_str
125
+ end
126
+
127
+ hash[key] = value
128
+ end
106
129
 
107
- public # end protected *****************************************************
130
+ hash
131
+ end # #from_simple_s
108
132
 
109
- end # class HashType
133
+ public # end protected *****************************************************
134
+
135
+ end # class HashType
136
+
137
+
138
+ # A {Hash} type with typed keys and/or values.
139
+ #
140
+ # @note
141
+ # Construct {HashOfType} types using the {.Hash} factory.
142
+ #
143
+
144
+ class HashOfType < HashType
110
145
 
146
+ # Attributes
147
+ # ========================================================================
111
148
 
112
- # A {Hash} type with typed keys and/or values.
149
+ # The type of the hash keys.
113
150
  #
114
- class HashOfType < HashType
115
-
116
- # Attributes
117
- # ========================================================================
118
-
119
- # The type of the hash keys.
120
- #
121
- # @return [NRSER::Types::Type]
122
- #
123
- attr_reader :keys
124
-
125
-
126
- # The type of the hash values.
127
- #
128
- # @return [NRSER::Types::Type]
129
- #
130
- attr_reader :values
131
-
132
-
133
- # Constructor
134
- # ========================================================================
135
-
136
- def initialize keys: NRSER::Types.any,
137
- values: NRSER::Types.any,
138
- **options
139
- super **options
140
-
141
- @keys = NRSER::Types.make keys
142
- @values = NRSER::Types.make values
143
- end
144
-
145
-
146
- # Instance Methods
147
- # ========================================================================
148
-
149
- # Overridden to check that both the {#keys} and {#values} types can
150
- # load from a string.
151
- #
152
- # @see NRSER::Types::Type#has_from_s?
153
- #
154
- def has_from_s?
155
- !@from_s.nil? || [keys, values].all?( &:has_from_s )
156
- end
157
-
158
-
159
- # @see NRSER::Types::Type#test
160
- #
161
- # @return [Boolean]
162
- #
163
- def test? value
164
- return false unless super( value )
165
-
166
- value.all? { |k, v|
167
- keys.test( k ) && values.test( v )
168
- }
169
- end
170
-
171
-
172
- # @see NRSER::Types::Type#explain
173
- #
174
- # @return [String]
175
- #
176
- def explain
177
- "Hash<#{ keys.explain }, #{ values.explain }>"
178
- end
179
-
180
- end # HashType
151
+ # @return [NRSER::Types::Type]
152
+ #
153
+ attr_reader :keys
154
+
155
+
156
+ # The type of the hash values.
157
+ #
158
+ # @return [NRSER::Types::Type]
159
+ #
160
+ attr_reader :values
161
+
162
+
163
+ # Constructor
164
+ # ========================================================================
165
+
166
+ def initialize keys: NRSER::Types.any,
167
+ values: NRSER::Types.any,
168
+ **options
169
+ super **options
181
170
 
171
+ @keys = NRSER::Types.make keys
172
+ @values = NRSER::Types.make values
173
+ end
174
+
182
175
 
183
- # Type satisfied by {Hash} instances.
176
+ # Instance Methods
177
+ # ========================================================================
178
+
179
+ # Overridden to check that both the {#keys} and {#values} types can
180
+ # load from a string.
184
181
  #
185
- # @param [Array] *args
186
- # Passed to {NRSER::Types::HashType#initialize} unless empty.
182
+ # @see NRSER::Types::Type#has_from_s?
187
183
  #
188
- # @return [NRSER::Types::HASH]
189
- # If `args` are empty.
184
+ def has_from_s?
185
+ !@from_s.nil? || [keys, values].all?( &:has_from_s )
186
+ end
187
+
188
+
189
+ # @see NRSER::Types::Type#test
190
190
  #
191
- # @return [NRSER::Types::Type]
192
- # Newly constructed hash type from `args`.
191
+ # @return [Boolean]
193
192
  #
194
- # @todo
195
- # Make `map` into it's own looser interface for "hash-like" object API.
193
+ def test? value
194
+ return false unless super( value )
195
+
196
+ value.all? { |k, v|
197
+ keys.test( k ) && values.test( v )
198
+ }
199
+ end
200
+
201
+
202
+ # @see NRSER::Types::Type#explain
196
203
  #
197
- def_factory(
198
- :hash_type,
199
- aliases: [ :dict, :hash_, :map ]
200
- ) do |**kwds|
201
- if kwds.key?( :keys ) || kwds.key?( :values )
202
- HashOfType.new **kwds
203
- else
204
- HashType.new **kwds
205
- end
204
+ # @return [String]
205
+ #
206
+ def explain
207
+ "Hash<#{ keys.explain }, #{ values.explain }>"
206
208
  end
207
209
 
208
- end
210
+ end # HashType
211
+
212
+
213
+ # @!group Hash Type Factories
214
+ # ----------------------------------------------------------------------------
215
+
216
+ # @!method self.Hash keys: self.Top, values: self.Top, **options
217
+ # Type satisfied by {Hash} instances with optional key and value types.
218
+ #
219
+ # @param [TYPE] keys
220
+ # Type for the hash keys. Will be made into a type by {.make} if it's not
221
+ # one already.
222
+ #
223
+ # **WARNING** Don't pass `nil` unless you mean that all the keys must be
224
+ # `nil`! Omit the keyword or pass {.Top}.
225
+ #
226
+ # @param [TYPE] values
227
+ # Type for the hash values. Will be made into a type by {.make} if it's not
228
+ # one already.
229
+ #
230
+ # **WARNING** Don't pass `nil` unless you mean that all the values must be
231
+ # `nil`! Omit the keyword or pass {.Top}.
232
+ #
233
+ # @param [Hash] options
234
+ # Passed to {Type#initialize}.
235
+ #
236
+ # @return [HashType]
237
+ #
238
+ def_type :Hash,
239
+ aliases: [ :dict, :hash_type ],
240
+ parameterize: [ :keys, :values ],
241
+ &->( keys: self.Top, values: self.Top, **options ) do
242
+ if keys != self.Top || values != self.Top
243
+ HashOfType.new keys: keys, values: values, **options
244
+ else
245
+ HashType.new **options
246
+ end
247
+ end # .Hash
248
+
249
+ # @!endgroup Hash Type Factories # *******************************************
250
+
251
+
252
+ # /Namespace
253
+ # ========================================================================
254
+
255
+ end # module Types
256
+ end # module NRSER
@@ -1,39 +1,76 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
- module NRSER::Types
5
-
6
- # Type that tests value for membership in a group object via that object's
7
- # `#include?` method.
8
- #
9
- # @todo
10
- # I think I want to get rid of {.where}... which would elevate this to
11
- # it's own class as a "fundamental" concept (I guess)... not so sure,
12
- # really. The idea of membership is pretty wide-spread and important,
13
- # but it's a bit a vague and inconsistently implemented things.
14
- #
15
- # @param [#include?] group
16
- # `#include?` will be called on this value to determine type membership.
17
- #
18
- # @return [NRSER::Types::Type]
19
- #
20
- def_factory(
21
- :in,
22
- aliases: [ :member_of ],
23
- ) do |group, **options|
24
- unless group.respond_to? :include?
25
- raise NRSER::ArgumentError,
26
- "In `group` must respond to `:include?`",
27
- group: group
28
- end
29
-
30
- # Provide a some-what useful default name
31
- options[:name] ||= "In<#{ NRSER.smart_ellipsis group.inspect, 64 }>"
32
-
33
- # Unless a `from_s` is provided, just use the identity
34
- options[:from_s] ||= ->( s ) { s }
35
-
36
- where( **options ) { |value| group.include? value }
37
- end # .in
38
-
39
- end # module NRSER::Types
4
+ # Requirements
5
+ # =======================================================================
6
+
7
+ # Project / Package
8
+ # -----------------------------------------------------------------------
9
+
10
+ require 'nrser/errors/type_error'
11
+
12
+ # Namespace
13
+ # ========================================================================
14
+
15
+ module NRSER
16
+ module Types
17
+
18
+
19
+ # Definitions
20
+ # ========================================================================
21
+
22
+ # @!group In Type Factories
23
+ # ----------------------------------------------------------------------------
24
+
25
+ #@!method self.In group, **options
26
+ # Type that tests value for membership in a group object via that object's
27
+ # `#include?` method.
28
+ #
29
+ # @todo
30
+ # I think I want to get rid of {.where}... which would elevate this to
31
+ # it's own class as a "fundamental" concept (I guess)... not so sure,
32
+ # really. The idea of membership is pretty wide-spread and important,
33
+ # but it's a bit a vague and inconsistently implemented things.
34
+ #
35
+ # @param [#include?] group
36
+ # `#include?` will be called on this value to determine type membership.
37
+ #
38
+ # @param [Hash] options
39
+ # Passed to {Type#initialize}.
40
+ #
41
+ # @return [Type]
42
+ #
43
+ # @raise [NRSER::TypeError]
44
+ # If `group` doesn't respond to `#include?`.
45
+ #
46
+ def_type :In,
47
+ aliases: [ :member_of ],
48
+ from_s: ->( s ) { s },
49
+ default_name: ->( group, **options ) {
50
+ "In<#{ NRSER.smart_ellipsis group.inspect, 64 }>"
51
+ },
52
+ parameterize: :group,
53
+ &->( group, **options ) do
54
+ unless group.respond_to? :include?
55
+ raise NRSER::TypeError,
56
+ "In `group` must respond to `:include?`",
57
+ group: group
58
+ end
59
+
60
+ # TODO This is a step in the right direction (from anon {Proc}) but I
61
+ # now think what we really want is
62
+ #
63
+ # where group, :include?
64
+ #
65
+ self.Where group.method( :include? ), **options
66
+ end # .In
67
+
68
+ # @!endgroup In Type Factories # *********************************************
69
+
70
+
71
+ # /Namespace
72
+ # ========================================================================
73
+
74
+ end # module Types
75
+ end # module NRSER
76
+