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,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
+